mirror of
https://github.com/go-gitea/gitea
synced 2026-02-10 13:28:10 +00:00
Compare commits
36 Commits
v1.15.0-rc2
...
v1.15.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7e7477c45 | ||
|
|
0840a508b4 | ||
|
|
5ceff8fda2 | ||
|
|
778a0bf758 | ||
|
|
f19ccd8f6a | ||
|
|
b6e4688874 | ||
|
|
25437672bf | ||
|
|
0dc808212b | ||
|
|
b6508b872b | ||
|
|
d89029ebac | ||
|
|
62315ea731 | ||
|
|
86861ee135 | ||
|
|
d2d99a25b7 | ||
|
|
e483ec8b0d | ||
|
|
46d62ad896 | ||
|
|
428d58f8da | ||
|
|
1a2256bf44 | ||
|
|
20601f8463 | ||
|
|
619e6d6400 | ||
|
|
f438b6f33b | ||
|
|
c47065cc29 | ||
|
|
719e2f26d5 | ||
|
|
40687a2160 | ||
|
|
f9120092c1 | ||
|
|
a17edf446f | ||
|
|
ff8fadd2be | ||
|
|
5fe7c0ed7b | ||
|
|
763e4196ba | ||
|
|
903bdefb58 | ||
|
|
840d240a61 | ||
|
|
7365b4e757 | ||
|
|
e10cd3da1e | ||
|
|
693275455e | ||
|
|
91527434d0 | ||
|
|
89f680aa04 | ||
|
|
67942ac1a9 |
+8
-8
@@ -15,12 +15,12 @@ trigger:
|
||||
steps:
|
||||
- name: deps-frontend
|
||||
pull: always
|
||||
image: node:16
|
||||
image: node:14
|
||||
commands:
|
||||
- make node_modules
|
||||
|
||||
- name: lint-frontend
|
||||
image: node:16
|
||||
image: node:14
|
||||
commands:
|
||||
- make lint-frontend
|
||||
depends_on: [deps-frontend]
|
||||
@@ -58,7 +58,7 @@ steps:
|
||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||
|
||||
- name: checks-frontend
|
||||
image: node:16
|
||||
image: node:14
|
||||
commands:
|
||||
- make checks-frontend
|
||||
depends_on: [deps-frontend]
|
||||
@@ -71,20 +71,20 @@ steps:
|
||||
depends_on: [lint-backend]
|
||||
|
||||
- name: test-frontend
|
||||
image: node:16
|
||||
image: node:14
|
||||
commands:
|
||||
- make test-frontend
|
||||
depends_on: [lint-frontend]
|
||||
|
||||
- name: build-frontend
|
||||
image: node:16
|
||||
image: node:14
|
||||
commands:
|
||||
- make frontend
|
||||
depends_on: [test-frontend]
|
||||
|
||||
- name: build-backend-no-gcc
|
||||
pull: always
|
||||
image: golang:1.14 # this step is kept as the lowest version of golang that we support
|
||||
image: golang:1.16 # this step is kept as the lowest version of golang that we support
|
||||
environment:
|
||||
GO111MODULE: on
|
||||
GOPROXY: off
|
||||
@@ -503,7 +503,7 @@ steps:
|
||||
pull: always
|
||||
image: techknowlogick/xgo:go-1.16.x
|
||||
commands:
|
||||
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
|
||||
- curl -sL https://deb.nodesource.com/setup_14.x | bash - && apt-get install -y nodejs
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make release
|
||||
environment:
|
||||
@@ -599,7 +599,7 @@ steps:
|
||||
pull: always
|
||||
image: techknowlogick/xgo:go-1.16.x
|
||||
commands:
|
||||
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
|
||||
- curl -sL https://deb.nodesource.com/setup_14.x | bash - && apt-get install -y nodejs
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make release
|
||||
environment:
|
||||
|
||||
@@ -2,6 +2,7 @@ root: true
|
||||
reportUnusedDisableDirectives: true
|
||||
|
||||
ignorePatterns:
|
||||
- /web_src/js/vendor
|
||||
- /templates/base/head.tmpl
|
||||
- /templates/repo/activity.tmpl
|
||||
- /templates/repo/view_file.tmpl
|
||||
|
||||
+55
-16
@@ -4,20 +4,7 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.15.0-rc2](https://github.com/go-gitea/gitea/releases/tag/v1.15.0-rc2) - 2021-07-22
|
||||
|
||||
* BUGFIXES
|
||||
* Restore creation of git-daemon-export-ok files (#16508) (#16514)
|
||||
* Fix data race in bleve indexer (#16474) (#16509)
|
||||
* Restore CORS on git smart http protocol (#16496) (#16506)
|
||||
* Fix race in log (#16490) (#16505)
|
||||
* Fix prepareWikiFileName to respect existing unescaped files (#16487) (#16498)
|
||||
* Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16480)
|
||||
* Update notification table with only latest data (#16445) (#16469)
|
||||
* Revert to use alpine 3.13 to fix multiple seccomp related issues with Docker <20 (#16451) (#16452)
|
||||
* Fix crash following ldap authentication update (#16447) (#16448)
|
||||
|
||||
## [1.15.0-rc1](https://github.com/go-gitea/gitea/releases/tag/v1.15.0-rc1) - 2021-07-15
|
||||
## [1.15.0](https://github.com/go-gitea/gitea/releases/tag/v1.15.0) - 2021-08-21
|
||||
|
||||
* BREAKING
|
||||
* Make app.ini permissions more restrictive (#16266)
|
||||
@@ -32,9 +19,15 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Move (custom) assets into subpath `/assets` (#15219)
|
||||
* Use level config in log section when sub log section not set level (#15176)
|
||||
* Links in markdown should be absolute to the repository not the server (#15088)
|
||||
* Upgrade to the latest version of golang-jwt (#16590) (#16606)
|
||||
* Set minimum supported version of go to 1.16 (#16710)
|
||||
* SECURITY
|
||||
* Encrypt LDAP bind password in db with SECRET_KEY (#15547)
|
||||
* Remove random password in Dockerfiles (#15362)
|
||||
* Upgrade to the latest version of golang-jwt and increase minimum go to 1.15 (#16590) (#16606)
|
||||
* Correctly create of git-daemon-export-ok files (#16508) (#16514)
|
||||
* Don't show private user's repo in explore view (#16550) (#16554)
|
||||
* Update node tar dependency to 6.1.6 (#16622) (#16623)
|
||||
* FEATURES
|
||||
* Update Go-Git to take advantage of LargeObjectThreshold (#16316)
|
||||
* Support custom mime type mapping for text files (#16304)
|
||||
@@ -55,7 +48,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Add LFS Migration and Mirror (#14726)
|
||||
* Improve notifications for WIP draft PR's (#14663)
|
||||
* Disable Stars config option (#14653)
|
||||
* Add option to provide signature for a token to verify key ownership (#14054)
|
||||
* GPG Key Ownership verification with Signed Token (#14054)
|
||||
* OAuth2 auto-register (#5123)
|
||||
* API
|
||||
* Return updated repository when changing repository using API (#16420)
|
||||
@@ -75,6 +68,8 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Add Active and ProhibitLogin to API (#15689)
|
||||
* Add Location, Website and Description to API (#15675)
|
||||
* Expose resolver via API (#15167)
|
||||
* Swagger AccessToken fixes (#16574) (#16597)
|
||||
* Set AllowedHeaders on API CORS handler (#16524) (#16618)
|
||||
* ENHANCEMENTS
|
||||
* Support HTTP/2 in Let's Encrypt (#16371)
|
||||
* Introduce NotifySubjectType (#16320)
|
||||
@@ -200,6 +195,41 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Add NeedPostProcess for Parser interface to improve performance of csv parser and some external parser (#15153)
|
||||
* Add code block highlight to orgmode back (#14222)
|
||||
* Remove User.GetOrganizations() (#14032)
|
||||
* Restore Accessibility for Dropdown (#16576) (#16617)
|
||||
* Pass down SignedUserName down to AccessLogger context (#16605) (#16616)
|
||||
* Fix table alignment in markdown (#16596) (#16602)
|
||||
* Fix 500 on first wiki page (#16586) (#16598)
|
||||
* Lock goth/gothic and Re-attempt OAuth2 registration on login if registration failed at startup (#16564) (#16570)
|
||||
* Upgrade levelqueue to v0.4.0 (#16560) (#16561)
|
||||
* Handle too long PR titles correctly (#16517) (#16549)
|
||||
* Fix data race in bleve indexer (#16474) (#16509)
|
||||
* Restore CORS on git smart http protocol (#16496) (#16506)
|
||||
* Fix race in log (#16490) (#16505)
|
||||
* Fix prepareWikiFileName to respect existing unescaped files (#16487) (#16498)
|
||||
* Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16480)
|
||||
* Update notification table with only latest data (#16445) (#16469)
|
||||
* Fix crash following ldap authentication update (#16447) (#16448)
|
||||
* Fix direct creation of external users on admin page (partial #16612) (#16613)
|
||||
* Prevent 500 on draft releases without tag (#16634) (#16636)
|
||||
* Restore creation of git-daemon-export-ok files (#16508) (#16514)
|
||||
* Fix data race in bleve indexer (#16474) (#16509)
|
||||
* Restore CORS on git smart http protocol (#16496) (#16506)
|
||||
* Fix race in log (#16490) (#16505)
|
||||
* Fix prepareWikiFileName to respect existing unescaped files (#16487) (#16498)
|
||||
* Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16480)
|
||||
* Update notification table with only latest data (#16445) (#16469)
|
||||
* Fix crash following ldap authentication update (#16447) (#16448)
|
||||
* Restore compatibility with SQLServer 2008 R2 in migrations (#16638)
|
||||
* Fix direct creation of external users on admin page (#16613)
|
||||
* Fix go-git implementation of GetNote when passed a non-existent commit (#16658) (#16659)
|
||||
* Fix NPE in fuzzer (#16680) (#16682)
|
||||
* Set issue_index when finishing migration (#16685) (#16687)
|
||||
* Skip patch download when no patch file exists (#16356) (#16681)
|
||||
* Ensure empty lines are copiable and final new line too (#16678) (#16692)
|
||||
* Fix wrong user in OpenID response (#16736) (#16741)
|
||||
* Do not use thin scrollbars on Firefox (#16738) (#16745)
|
||||
* Recreate Tables should Recreate indexes on MySQL (#16718) (#16739)
|
||||
* Keep attachments on tasklist update (#16750) (#16757)
|
||||
* TESTING
|
||||
* Bump `postgres` and `mysql` versions (#15710)
|
||||
* Add tests for clone from wiki (#15513)
|
||||
@@ -210,7 +240,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Fix mirror_lfs source string in en-US locale (#15369)
|
||||
* BUILD
|
||||
* Upgrade xorm to v1.1.1 (#16339)
|
||||
* Alpine 3.14 released (#16170)
|
||||
* Disable legal comments in esbuild (#15929)
|
||||
* Switch to Node 16 to build fronted (#15804)
|
||||
* Use esbuild to minify CSS (#15756)
|
||||
@@ -229,6 +258,16 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Remove utf8 option from installation page (#16126)
|
||||
* Use Wants= over Requires= in systemd file (#15897)
|
||||
|
||||
## [1.14.6](https://github.com/go-gitea/gitea/releases/tag/v1.14.6) - 2021-08-04
|
||||
|
||||
* SECURITY
|
||||
* Bump github.com/markbates/goth from v1.67.1 to v1.68.0 (#16538) (#16540)
|
||||
* Switch to maintained JWT lib (#16532) (#16535)
|
||||
* Upgrade to latest version of golang-jwt (as forked for 1.14) (#16590) (#16607)
|
||||
* BUGFIXES
|
||||
* Add basic edit ldap auth test & actually fix #16252 (#16465) (#16495)
|
||||
* Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479) (#16481)
|
||||
|
||||
## [1.14.5](https://github.com/go-gitea/gitea/releases/tag/v1.14.5) - 2021-07-16
|
||||
|
||||
* SECURITY
|
||||
|
||||
@@ -25,7 +25,7 @@ HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
||||
COMMA := ,
|
||||
|
||||
XGO_VERSION := go-1.16.x
|
||||
MIN_GO_VERSION := 001014000
|
||||
MIN_GO_VERSION := 001016000
|
||||
MIN_NODE_VERSION := 012017000
|
||||
|
||||
DOCKER_IMAGE ?= gitea/gitea
|
||||
@@ -200,7 +200,7 @@ help:
|
||||
go-check:
|
||||
$(eval GO_VERSION := $(shell printf "%03d%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9.]+' | tr '.' ' ');))
|
||||
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
|
||||
echo "Gitea requires Go 1.14 or greater to build. You can get it at https://golang.org/dl/"; \
|
||||
echo "Gitea requires Go 1.16 or greater to build. You can get it at https://golang.org/dl/"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@@ -699,6 +699,7 @@ fomantic:
|
||||
cd $(FOMANTIC_WORK_DIR) && npm install --no-save
|
||||
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
|
||||
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
|
||||
cp -f web_src/js/vendor/dropdown.js $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/definitions/modules
|
||||
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
|
||||
|
||||
.PHONY: webpack
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/lfs"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/golang-jwt/jwt"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/kballard/go-shellquote"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@ params:
|
||||
description: Git with a cup of tea
|
||||
author: The Gitea Authors
|
||||
website: https://docs.gitea.io
|
||||
version: 1.14.4
|
||||
minGoVersion: 1.14
|
||||
version: 1.14.6
|
||||
minGoVersion: 1.16
|
||||
goVersion: 1.16
|
||||
minNodeVersion: 12.17
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ require (
|
||||
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e
|
||||
gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e
|
||||
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee
|
||||
gitea.com/lunny/levelqueue v0.3.0
|
||||
gitea.com/lunny/levelqueue v0.4.1
|
||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210705153151-cc34b1f6908b // indirect
|
||||
@@ -28,7 +28,6 @@ require (
|
||||
github.com/couchbase/gomemcached v0.1.2 // indirect
|
||||
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401 // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.10.0
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/djherbis/buffer v1.2.0
|
||||
github.com/djherbis/nio/v3 v3.0.1
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
@@ -51,6 +50,7 @@ require (
|
||||
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
|
||||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-github/v32 v32.1.0
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
@@ -75,7 +75,7 @@ require (
|
||||
github.com/lafriks/xormstore v1.4.0
|
||||
github.com/lib/pq v1.10.2
|
||||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
|
||||
github.com/markbates/goth v1.67.1
|
||||
github.com/markbates/goth v1.68.0
|
||||
github.com/mattn/go-isatty v0.0.13
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.7
|
||||
@@ -143,3 +143,5 @@ require (
|
||||
)
|
||||
|
||||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||
|
||||
replace github.com/golang-jwt/jwt v3.2.1+incompatible => github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
|
||||
@@ -49,8 +49,8 @@ gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e h1:YjaQU6XFicdhPN+Ml
|
||||
gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e/go.mod h1:nfA7JaGv3hbGQ1ktdhAsZhdS84qKffI8NMlHr+Opsog=
|
||||
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee h1:9U6HuKUBt/cGK6T/64dEuz0r7Yp97WAAEJvXHDlY3ws=
|
||||
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee/go.mod h1:Ozg8IchVNb/Udg+ui39iHRYqVHSvf3C99ixdpLR8Vu0=
|
||||
gitea.com/lunny/levelqueue v0.3.0 h1:MHn1GuSZkxvVEDMyAPqlc7A3cOW+q8RcGhRgH/xtm6I=
|
||||
gitea.com/lunny/levelqueue v0.3.0/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
||||
gitea.com/lunny/levelqueue v0.4.1 h1:RZ+AFx5gBsZuyqCvofhAkPQ9uaVDPJnsULoJZIYaJNw=
|
||||
gitea.com/lunny/levelqueue v0.4.1/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
||||
github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U=
|
||||
@@ -241,7 +241,6 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xb
|
||||
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8=
|
||||
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
@@ -476,6 +475,8 @@ github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 h1:yXtpJr/LV6PFu4nTLgfjQ
|
||||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14/go.mod h1:jPoNZLWDAqA5N3G5amEoiNbhVrmM+ZQEcnQvNQ2KaZk=
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0=
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
@@ -762,8 +763,8 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
|
||||
github.com/markbates/goth v1.67.1 h1:gU5B0pzHVyhnJPwGynfFnkfvaQ39C1Sy+ewdl+bhAOw=
|
||||
github.com/markbates/goth v1.67.1/go.mod h1:EyLFHGU5ySr2GXRDyJH5nu2dA7parbC8QwIYW/rGcWg=
|
||||
github.com/markbates/goth v1.68.0 h1:90sKvjRAKHcl9V2uC9x/PJXeD78cFPiBsyP1xVhoQfA=
|
||||
github.com/markbates/goth v1.68.0/go.mod h1:V2VcDMzDiMHW+YmqYl7i0cMiAUeCkAe4QE6jRKBhXZw=
|
||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
|
||||
@@ -160,7 +160,7 @@ func getLatestCommitStatus(e Engine, repoID int64, sha string, listOptions ListO
|
||||
if len(ids) == 0 {
|
||||
return statuses, nil
|
||||
}
|
||||
return statuses, x.In("id", ids).Find(&statuses)
|
||||
return statuses, e.In("id", ids).Find(&statuses)
|
||||
}
|
||||
|
||||
// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
|
||||
|
||||
@@ -5,3 +5,19 @@
|
||||
scope: "openid profile"
|
||||
created_unix: 1546869730
|
||||
updated_unix: 1546869730
|
||||
|
||||
- id: 2
|
||||
user_id: 3
|
||||
application_id: 1
|
||||
counter: 1
|
||||
scope: "openid"
|
||||
created_unix: 1546869730
|
||||
updated_unix: 1546869730
|
||||
|
||||
- id: 3
|
||||
user_id: 5
|
||||
application_id: 1
|
||||
counter: 1
|
||||
scope: "openid profile email"
|
||||
created_unix: 1546869730
|
||||
updated_unix: 1546869730
|
||||
@@ -982,6 +982,31 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
|
||||
return opts.Issue.addCrossReferences(e, doer, false)
|
||||
}
|
||||
|
||||
// RecalculateIssueIndexForRepo create issue_index for repo if not exist and
|
||||
// update it based on highest index of existing issues assigned to a repo
|
||||
func RecalculateIssueIndexForRepo(repoID int64) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := upsertResourceIndex(sess, "issue_index", repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var max int64
|
||||
if _, err := sess.Select(" MAX(`index`)").Table("issue").Where("repo_id=?", repoID).Get(&max); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := sess.Exec("UPDATE `issue_index` SET max_index=? WHERE group_id=?", max, repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
// NewIssue creates new issue with labels for repository.
|
||||
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
|
||||
idx, err := GetNextResourceIndex("issue_index", repo.ID)
|
||||
|
||||
+45
-15
@@ -9,6 +9,8 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// Stopwatch represents a stopwatch for time tracking.
|
||||
@@ -61,8 +63,12 @@ func StopwatchExists(userID, issueID int64) bool {
|
||||
|
||||
// HasUserStopwatch returns true if the user has a stopwatch
|
||||
func HasUserStopwatch(userID int64) (exists bool, sw *Stopwatch, err error) {
|
||||
return hasUserStopwatch(x, userID)
|
||||
}
|
||||
|
||||
func hasUserStopwatch(e Engine, userID int64) (exists bool, sw *Stopwatch, err error) {
|
||||
sw = new(Stopwatch)
|
||||
exists, err = x.
|
||||
exists, err = e.
|
||||
Where("user_id = ?", userID).
|
||||
Get(sw)
|
||||
return
|
||||
@@ -70,11 +76,23 @@ func HasUserStopwatch(userID int64) (exists bool, sw *Stopwatch, err error) {
|
||||
|
||||
// CreateOrStopIssueStopwatch will create or remove a stopwatch and will log it into issue's timeline.
|
||||
func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
||||
sw, exists, err := getStopwatch(x, user.ID, issue.ID)
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := createOrStopIssueStopwatch(sess, user, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func createOrStopIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
||||
sw, exists, err := getStopwatch(e, user.ID, issue.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := issue.loadRepo(x); err != nil {
|
||||
if err := issue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -90,11 +108,11 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
||||
Time: timediff,
|
||||
}
|
||||
|
||||
if _, err := x.Insert(tt); err != nil {
|
||||
if _, err := e.Insert(tt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := CreateComment(&CreateCommentOptions{
|
||||
if _, err := createComment(e, &CreateCommentOptions{
|
||||
Doer: user,
|
||||
Issue: issue,
|
||||
Repo: issue.Repo,
|
||||
@@ -104,21 +122,21 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := x.Delete(sw); err != nil {
|
||||
if _, err := e.Delete(sw); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// if another stopwatch is running: stop it
|
||||
exists, sw, err := HasUserStopwatch(user.ID)
|
||||
exists, sw, err := hasUserStopwatch(e, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
issue, err := getIssueByID(x, sw.IssueID)
|
||||
issue, err := getIssueByID(e, sw.IssueID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := CreateOrStopIssueStopwatch(user, issue); err != nil {
|
||||
if err := createOrStopIssueStopwatch(e, user, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -129,11 +147,11 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
||||
IssueID: issue.ID,
|
||||
}
|
||||
|
||||
if _, err := x.Insert(sw); err != nil {
|
||||
if _, err := e.Insert(sw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := CreateComment(&CreateCommentOptions{
|
||||
if _, err := createComment(e, &CreateCommentOptions{
|
||||
Doer: user,
|
||||
Issue: issue,
|
||||
Repo: issue.Repo,
|
||||
@@ -147,21 +165,33 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
||||
|
||||
// CancelStopwatch removes the given stopwatch and logs it into issue's timeline.
|
||||
func CancelStopwatch(user *User, issue *Issue) error {
|
||||
sw, exists, err := getStopwatch(x, user.ID, issue.ID)
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cancelStopwatch(sess, user, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func cancelStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
||||
sw, exists, err := getStopwatch(e, user.ID, issue.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exists {
|
||||
if _, err := x.Delete(sw); err != nil {
|
||||
if _, err := e.Delete(sw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := issue.loadRepo(x); err != nil {
|
||||
if err := issue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := CreateComment(&CreateCommentOptions{
|
||||
if _, err := createComment(e, &CreateCommentOptions{
|
||||
Doer: user,
|
||||
Issue: issue,
|
||||
Repo: issue.Repo,
|
||||
|
||||
@@ -590,11 +590,26 @@ func recreateTable(sess *xorm.Session, bean interface{}) error {
|
||||
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 {
|
||||
@@ -836,7 +851,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||
}
|
||||
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'))",
|
||||
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 {
|
||||
@@ -847,17 +862,14 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||
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'))",
|
||||
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("ALTER TABLE `%s` DROP CONSTRAINT IF EXISTS `%s`", tableName, constraint)); err != nil {
|
||||
return fmt.Errorf("Drop table `%s` index constraint `%s`: %v", tableName, constraint, err)
|
||||
}
|
||||
if _, err := sess.Exec(fmt.Sprintf("DROP INDEX IF EXISTS `%[2]s` ON `%[1]s`", tableName, constraint)); err != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,11 +155,6 @@ func initOAuth2LoginSources() error {
|
||||
err := oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping)
|
||||
if err != nil {
|
||||
log.Critical("Unable to register source: %s due to Error: %v. This source will be disabled.", source.Name, err)
|
||||
source.IsActived = false
|
||||
if err = UpdateSource(source); err != nil {
|
||||
log.Critical("Unable to update source %s to disable it. Error: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/golang-jwt/jwt"
|
||||
uuid "github.com/google/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"xorm.io/xorm"
|
||||
|
||||
+1
-1
@@ -1125,7 +1125,7 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, overwriteO
|
||||
|
||||
// Give access to all members in teams with access to all repositories.
|
||||
if u.IsOrganization() {
|
||||
if err := u.GetTeams(&SearchTeamOptions{}); err != nil {
|
||||
if err := u.getTeams(ctx.e); err != nil {
|
||||
return fmt.Errorf("GetTeams: %v", err)
|
||||
}
|
||||
for _, t := range u.Teams {
|
||||
|
||||
+3
-5
@@ -217,16 +217,14 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
|
||||
cond = cond.And(accessibleRepositoryCondition(opts.Actor))
|
||||
}
|
||||
} else {
|
||||
// Not looking at private organisations
|
||||
// Not looking at private organisations and users
|
||||
// We should be able to see all non-private repositories that
|
||||
// isn't in a private or limited organisation.
|
||||
cond = cond.And(
|
||||
builder.Eq{"is_private": false},
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(
|
||||
builder.And(
|
||||
builder.Eq{"type": UserTypeOrganization},
|
||||
builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}),
|
||||
))))
|
||||
builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}),
|
||||
)))
|
||||
}
|
||||
|
||||
if opts.IsPrivate != util.OptionalBoolNone {
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/golang-jwt/jwt"
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package oauth2
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -34,6 +35,7 @@ import (
|
||||
var (
|
||||
sessionUsersStoreKey = "gitea-oauth2-sessions"
|
||||
providerHeaderKey = "gitea-oauth2-provider"
|
||||
gothRWMutex = sync.RWMutex{}
|
||||
)
|
||||
|
||||
// CustomURLMapping describes the urls values to use when customizing OAuth2 provider URLs
|
||||
@@ -60,6 +62,10 @@ func Init(x *xorm.Engine) error {
|
||||
|
||||
// Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk
|
||||
store.MaxLength(setting.OAuth2.MaxTokenLength)
|
||||
|
||||
gothRWMutex.Lock()
|
||||
defer gothRWMutex.Unlock()
|
||||
|
||||
gothic.Store = store
|
||||
|
||||
gothic.SetState = func(req *http.Request) string {
|
||||
@@ -82,6 +88,9 @@ func Auth(provider string, request *http.Request, response http.ResponseWriter)
|
||||
// normally the gothic library will write some custom stuff to the response instead of our own nice error page
|
||||
//gothic.BeginAuthHandler(response, request)
|
||||
|
||||
gothRWMutex.RLock()
|
||||
defer gothRWMutex.RUnlock()
|
||||
|
||||
url, err := gothic.GetAuthURL(response, request)
|
||||
if err == nil {
|
||||
http.Redirect(response, request, url, http.StatusTemporaryRedirect)
|
||||
@@ -95,6 +104,9 @@ func ProviderCallback(provider string, request *http.Request, response http.Resp
|
||||
// not sure if goth is thread safe (?) when using multiple providers
|
||||
request.Header.Set(providerHeaderKey, provider)
|
||||
|
||||
gothRWMutex.RLock()
|
||||
defer gothRWMutex.RUnlock()
|
||||
|
||||
user, err := gothic.CompleteUserAuth(response, request)
|
||||
if err != nil {
|
||||
return user, err
|
||||
@@ -108,6 +120,9 @@ func RegisterProvider(providerName, providerType, clientID, clientSecret, openID
|
||||
provider, err := createProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL, customURLMapping)
|
||||
|
||||
if err == nil && provider != nil {
|
||||
gothRWMutex.Lock()
|
||||
defer gothRWMutex.Unlock()
|
||||
|
||||
goth.UseProviders(provider)
|
||||
}
|
||||
|
||||
@@ -116,11 +131,17 @@ func RegisterProvider(providerName, providerType, clientID, clientSecret, openID
|
||||
|
||||
// RemoveProvider removes the given OAuth2 provider from the goth lib
|
||||
func RemoveProvider(providerName string) {
|
||||
gothRWMutex.Lock()
|
||||
defer gothRWMutex.Unlock()
|
||||
|
||||
delete(goth.GetProviders(), providerName)
|
||||
}
|
||||
|
||||
// ClearProviders clears all OAuth2 providers from the goth lib
|
||||
func ClearProviders() {
|
||||
gothRWMutex.Lock()
|
||||
defer gothRWMutex.Unlock()
|
||||
|
||||
goth.ClearProviders()
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package context
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -22,6 +23,8 @@ type routerLoggerOptions struct {
|
||||
Ctx map[string]interface{}
|
||||
}
|
||||
|
||||
var signedUserNameStringPointerKey interface{} = "signedUserNameStringPointerKey"
|
||||
|
||||
// AccessLogger returns a middleware to log access logger
|
||||
func AccessLogger() func(http.Handler) http.Handler {
|
||||
logger := log.GetLogger("access")
|
||||
@@ -29,11 +32,10 @@ func AccessLogger() func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
start := time.Now()
|
||||
next.ServeHTTP(w, req)
|
||||
identity := "-"
|
||||
if val := SignedUserName(req); val != "" {
|
||||
identity = val
|
||||
}
|
||||
r := req.WithContext(context.WithValue(req.Context(), signedUserNameStringPointerKey, &identity))
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
rw := w.(ResponseWriter)
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
@@ -275,6 +275,17 @@ func APIContexter() func(http.Handler) http.Handler {
|
||||
ctx.Data["CsrfToken"] = html.EscapeString(ctx.csrf.GetToken())
|
||||
|
||||
next.ServeHTTP(ctx.Resp, ctx.Req)
|
||||
|
||||
// Handle adding signedUserName to the context for the AccessLogger
|
||||
usernameInterface := ctx.Data["SignedUserName"]
|
||||
identityPtrInterface := ctx.Req.Context().Value(signedUserNameStringPointerKey)
|
||||
if usernameInterface != nil && identityPtrInterface != nil {
|
||||
username := usernameInterface.(string)
|
||||
identityPtr := identityPtrInterface.(*string)
|
||||
if identityPtr != nil && username != "" {
|
||||
*identityPtr = username
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,6 +774,17 @@ func Contexter() func(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
next.ServeHTTP(ctx.Resp, ctx.Req)
|
||||
|
||||
// Handle adding signedUserName to the context for the AccessLogger
|
||||
usernameInterface := ctx.Data["SignedUserName"]
|
||||
identityPtrInterface := ctx.Req.Context().Value(signedUserNameStringPointerKey)
|
||||
if usernameInterface != nil && identityPtrInterface != nil {
|
||||
username := usernameInterface.(string)
|
||||
identityPtr := identityPtrInterface.(*string)
|
||||
if identityPtr != nil && username != "" {
|
||||
*identityPtr = username
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
)
|
||||
|
||||
// NewInternalToken generate a new value intended to be used by INTERNAL_TOKEN.
|
||||
|
||||
@@ -36,6 +36,9 @@ func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note)
|
||||
remainingCommitID = remainingCommitID[2:]
|
||||
}
|
||||
if err != nil {
|
||||
if err == object.ErrDirectoryNotFound {
|
||||
return ErrNotExist{ID: remainingCommitID, RelPath: path}
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,3 +39,15 @@ func TestGetNestedNotes(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("Note 1"), note.Message)
|
||||
}
|
||||
|
||||
func TestGetNonExistentNotes(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
bareRepo1, err := OpenRepository(bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
defer bareRepo1.Close()
|
||||
|
||||
note := Note{}
|
||||
err = GetNote(context.Background(), bareRepo1, "non_existent_sha", ¬e)
|
||||
assert.Error(t, err)
|
||||
assert.IsType(t, ErrNotExist{}, err)
|
||||
}
|
||||
|
||||
@@ -166,6 +166,11 @@ func File(numLines int, fileName string, code []byte) map[int]string {
|
||||
}
|
||||
|
||||
htmlw.Flush()
|
||||
finalNewLine := false
|
||||
if len(code) > 0 {
|
||||
finalNewLine = code[len(code)-1] == '\n'
|
||||
}
|
||||
|
||||
m := make(map[int]string, numLines)
|
||||
for k, v := range strings.SplitN(htmlbuf.String(), "\n", numLines) {
|
||||
line := k + 1
|
||||
@@ -173,9 +178,17 @@ func File(numLines int, fileName string, code []byte) map[int]string {
|
||||
//need to keep lines that are only \n so copy/paste works properly in browser
|
||||
if content == "" {
|
||||
content = "\n"
|
||||
} else if content == `</span><span class="w">` {
|
||||
content += "\n</span>"
|
||||
}
|
||||
content = strings.TrimSuffix(content, `<span class="w">`)
|
||||
content = strings.TrimPrefix(content, `</span>`)
|
||||
m[line] = content
|
||||
}
|
||||
if finalNewLine {
|
||||
m[numLines+1] = "<span class=\"w\">\n</span>"
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// 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 highlight
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
func TestFile(t *testing.T) {
|
||||
setting.Cfg = ini.Empty()
|
||||
tests := []struct {
|
||||
name string
|
||||
numLines int
|
||||
fileName string
|
||||
code string
|
||||
want map[int]string
|
||||
}{
|
||||
{
|
||||
name: ".drone.yml",
|
||||
numLines: 12,
|
||||
fileName: ".drone.yml",
|
||||
code: `kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.13
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go get -u
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
`,
|
||||
want: map[int]string{
|
||||
1: `<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`,
|
||||
2: `<span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default</span>`,
|
||||
3: `<span class="w">
|
||||
</span>`,
|
||||
4: `<span class="w"></span><span class="nt">steps</span><span class="p">:</span>`,
|
||||
5: `<span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`,
|
||||
6: `<span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`,
|
||||
7: `<span class="w"> </span><span class="nt">environment</span><span class="p">:</span>`,
|
||||
8: `<span class="w"></span><span class="w"> </span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`,
|
||||
9: `<span class="w"> </span><span class="nt">commands</span><span class="p">:</span>`,
|
||||
10: `<span class="w"></span><span class="w"> </span>- <span class="l">go get -u</span>`,
|
||||
11: `<span class="w"> </span>- <span class="l">go build -v</span>`,
|
||||
12: `<span class="w"> </span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span><span class="w">
|
||||
</span>`,
|
||||
13: `<span class="w">
|
||||
</span>`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ".drone.yml - trailing space",
|
||||
numLines: 13,
|
||||
fileName: ".drone.yml",
|
||||
code: `kind: pipeline
|
||||
name: default ` + `
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.13
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
- go get -u
|
||||
- go build -v
|
||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
|
||||
`,
|
||||
want: map[int]string{
|
||||
1: `<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`,
|
||||
2: `<span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default </span>`,
|
||||
3: `<span class="w">
|
||||
</span>`,
|
||||
4: `<span class="w"></span><span class="nt">steps</span><span class="p">:</span>`,
|
||||
5: `<span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`,
|
||||
6: `<span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`,
|
||||
7: `<span class="w"> </span><span class="nt">environment</span><span class="p">:</span>`,
|
||||
8: `<span class="w"></span><span class="w"> </span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`,
|
||||
9: `<span class="w"> </span><span class="nt">commands</span><span class="p">:</span>`,
|
||||
10: `<span class="w"></span><span class="w"> </span>- <span class="l">go get -u</span>`,
|
||||
11: `<span class="w"> </span>- <span class="l">go build -v</span>`,
|
||||
12: `<span class="w"> </span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span>`,
|
||||
13: `<span class="w"> </span>`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := File(tt.numLines, tt.fileName, []byte(tt.code)); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("File() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -778,7 +778,7 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
|
||||
// extract repo and org name from matched link like
|
||||
// http://localhost:3000/gituser/myrepo/issues/1
|
||||
linkParts := strings.Split(path.Clean(link), "/")
|
||||
linkParts := strings.Split(link, "/")
|
||||
matchOrg := linkParts[len(linkParts)-4]
|
||||
matchRepo := linkParts[len(linkParts)-3]
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package markup_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -526,3 +527,18 @@ func BenchmarkEmojiPostprocess(b *testing.B) {
|
||||
assert.NoError(b, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuzz(t *testing.T) {
|
||||
s := "t/l/issues/8#/../../a"
|
||||
renderContext := RenderContext{
|
||||
URLPrefix: "https://example.com/go-gitea/gitea",
|
||||
Metas: map[string]string{
|
||||
"user": "go-gitea",
|
||||
"repo": "gitea",
|
||||
},
|
||||
}
|
||||
|
||||
err := PostProcess(&renderContext, strings.NewReader(s), io.Discard)
|
||||
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -87,7 +87,9 @@ func newParserContext(ctx *markup.RenderContext) parser.Context {
|
||||
func actualRender(ctx *markup.RenderContext, input io.Reader, output io.Writer) error {
|
||||
once.Do(func() {
|
||||
converter = goldmark.New(
|
||||
goldmark.WithExtensions(extension.Table,
|
||||
goldmark.WithExtensions(
|
||||
extension.NewTable(
|
||||
extension.WithTableCellAlignMethod(extension.TableCellAlignAttribute)),
|
||||
extension.Strikethrough,
|
||||
extension.TaskList,
|
||||
extension.DefinitionList,
|
||||
|
||||
@@ -555,6 +555,9 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR
|
||||
|
||||
// download patch file
|
||||
err := func() error {
|
||||
if pr.PatchURL == "" {
|
||||
return nil
|
||||
}
|
||||
// pr.PatchURL maybe a local file
|
||||
ret, err := uri.Open(pr.PatchURL)
|
||||
if err != nil {
|
||||
@@ -871,6 +874,11 @@ func (g *GiteaLocalUploader) Finish() error {
|
||||
return ErrRepoNotCreated
|
||||
}
|
||||
|
||||
// update issue_index
|
||||
if err := models.RecalculateIssueIndexForRepo(g.repo.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.repo.Status = models.RepositoryReady
|
||||
return models.UpdateRepositoryCols(g.repo, "status")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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 util
|
||||
|
||||
import "unicode/utf8"
|
||||
|
||||
// SplitStringAtByteN splits a string at byte n accounting for rune boundaries. (Combining characters are not accounted for.)
|
||||
func SplitStringAtByteN(input string, n int) (left, right string) {
|
||||
if len(input) <= n {
|
||||
left = input
|
||||
return
|
||||
}
|
||||
|
||||
if !utf8.ValidString(input) {
|
||||
left = input[:n-3] + "..."
|
||||
right = "..." + input[n-3:]
|
||||
return
|
||||
}
|
||||
|
||||
// in UTF8 "…" is 3 bytes so doesn't really gain us anything...
|
||||
end := 0
|
||||
for end <= n-3 {
|
||||
_, size := utf8.DecodeRuneInString(input[end:])
|
||||
if end+size > n-3 {
|
||||
break
|
||||
}
|
||||
end += size
|
||||
}
|
||||
|
||||
left = input[:end] + "…"
|
||||
right = "…" + input[end:]
|
||||
return
|
||||
}
|
||||
@@ -1248,8 +1248,8 @@ issues.dependency.remove=Odstranit
|
||||
issues.dependency.remove_info=Odstranit tuto závislost
|
||||
issues.dependency.added_dependency=`přidal(a) novou závislost %s`
|
||||
issues.dependency.removed_dependency=`odstranil(a) závislost %s`
|
||||
issues.dependency.issue_closing_blockedby=Uzavření tohoto požadavku na natažení je blokováno následujícími úkoly
|
||||
issues.dependency.pr_closing_blockedby=Uzavření tohoto úkolu je blokováno následujícími úkoly
|
||||
issues.dependency.pr_closing_blockedby=Uzavření tohoto požadavku na natažení je blokováno následujícími úkoly
|
||||
issues.dependency.issue_closing_blockedby=Uzavření tohoto úkolu je blokováno následujícími úkoly
|
||||
issues.dependency.issue_close_blocks=Tento úkol blokuje uzavření následujících úkolů
|
||||
issues.dependency.pr_close_blocks=Tento požadavek na natažení blokuje uzavření následujících úkolů
|
||||
issues.dependency.issue_close_blocked=Musíte zavřít všechny úkoly, které blokují tento úkol, aby jej bylo možné zavřít.
|
||||
|
||||
@@ -1326,8 +1326,8 @@ issues.dependency.remove=Entfernen
|
||||
issues.dependency.remove_info=Abhängigkeit löschen
|
||||
issues.dependency.added_dependency=`hat eine neue Abhängigkeit %s hinzugefügt`
|
||||
issues.dependency.removed_dependency=`hat eine Abhängigkeit %s entfernt`
|
||||
issues.dependency.issue_closing_blockedby=Das Schließen dieses Pull-Requests wird von den folgenden Issues blockiert
|
||||
issues.dependency.pr_closing_blockedby=Das Schließen dieses Issues wird von den folgenden Issues blockiert
|
||||
issues.dependency.pr_closing_blockedby=Das Schließen dieses Pull-Requests wird von den folgenden Issues blockiert
|
||||
issues.dependency.issue_closing_blockedby=Das Schließen dieses Issues wird von den folgenden Issues blockiert
|
||||
issues.dependency.issue_close_blocks=Dieses Issue blockiert die Schließung der folgenden Issues
|
||||
issues.dependency.pr_close_blocks=Dieser Pull-Request blockiert die Schließung der folgenden Issues
|
||||
issues.dependency.issue_close_blocked=Du musst alle Issues, die dieses Issue blockieren, schließen, bevor du es schließen kannst.
|
||||
|
||||
@@ -1326,8 +1326,8 @@ issues.dependency.remove = Remove
|
||||
issues.dependency.remove_info = Remove this dependency
|
||||
issues.dependency.added_dependency = `added a new dependency %s`
|
||||
issues.dependency.removed_dependency = `removed a dependency %s`
|
||||
issues.dependency.issue_closing_blockedby = Closing this pull request is blocked by the following issues
|
||||
issues.dependency.pr_closing_blockedby = Closing this issue is blocked by the following issues
|
||||
issues.dependency.pr_closing_blockedby = Closing this pull request is blocked by the following issues
|
||||
issues.dependency.issue_closing_blockedby = Closing this issue is blocked by the following issues
|
||||
issues.dependency.issue_close_blocks = This issue blocks closing of the following issues
|
||||
issues.dependency.pr_close_blocks = This pull request blocks closing of the following issues
|
||||
issues.dependency.issue_close_blocked = You need to close all issues blocking this issue before you can close it.
|
||||
|
||||
@@ -1326,8 +1326,8 @@ issues.dependency.remove=Eliminar
|
||||
issues.dependency.remove_info=Eliminar esta dependencia
|
||||
issues.dependency.added_dependency=`añadida una nueva dependencia %s`
|
||||
issues.dependency.removed_dependency=`eliminada una dependencia %s`
|
||||
issues.dependency.issue_closing_blockedby=Cerrar este pull request está bloqueado por las siguientes issues
|
||||
issues.dependency.pr_closing_blockedby=Cierre de esta incidencia es bloqueado por las siguientes incidencias
|
||||
issues.dependency.pr_closing_blockedby=Cerrar este pull request está bloqueado por las siguientes issues
|
||||
issues.dependency.issue_closing_blockedby=Cierre de esta incidencia es bloqueado por las siguientes incidencias
|
||||
issues.dependency.issue_close_blocks=Esta incidencia bloquea el cierre de las siguientes incidencias
|
||||
issues.dependency.pr_close_blocks=Este pull request bloquea el cierre de las siguientes incidencias
|
||||
issues.dependency.issue_close_blocked=Necesita cerrar todos las incidencias que bloquean esta incidencia antes de que se puede cerrar.
|
||||
|
||||
@@ -1070,8 +1070,8 @@ issues.dependency.remove=حذف/ساقط کردن
|
||||
issues.dependency.remove_info=حذف این وابستگی
|
||||
issues.dependency.added_dependency=`%s یک مخزن جدید اضافه کرد`
|
||||
issues.dependency.removed_dependency=`%s یک وابستگی را حذف کرد`
|
||||
issues.dependency.issue_closing_blockedby=بستن این تقاضای واکشی وسط موضوعات زیر رد/ مسدود شده است
|
||||
issues.dependency.pr_closing_blockedby=بستن این موضوع وسط موضوعات زیر رد/ مسدود شده است
|
||||
issues.dependency.pr_closing_blockedby=بستن این تقاضای واکشی وسط موضوعات زیر رد/ مسدود شده است
|
||||
issues.dependency.issue_closing_blockedby=بستن این موضوع وسط موضوعات زیر رد/ مسدود شده است
|
||||
issues.dependency.issue_close_blocks=این مسئله با توجه به موضوعات مطرح شده مسدود شده است
|
||||
issues.dependency.pr_close_blocks=این تقاضای واکشی با توجه به موضوعات مطرح شده مسدود شده است
|
||||
issues.dependency.issue_close_blocked=شما نیاز به بستن تمامی مسائل مسدود شده مسئله قبل بستن آن هستید.
|
||||
|
||||
@@ -1277,8 +1277,8 @@ issues.dependency.remove=Supprimer
|
||||
issues.dependency.remove_info=Supprimer cette dépendance
|
||||
issues.dependency.added_dependency=`a ajouté une nouvelle dépendance %s`
|
||||
issues.dependency.removed_dependency=`a supprimé une dépendance %s`
|
||||
issues.dependency.issue_closing_blockedby=La clôture de cette demande d'ajout est bloquée par les tickets suivants
|
||||
issues.dependency.pr_closing_blockedby=La clôture de ce ticket est bloquée par les tickets suivants
|
||||
issues.dependency.pr_closing_blockedby=La clôture de cette demande d'ajout est bloquée par les tickets suivants
|
||||
issues.dependency.issue_closing_blockedby=La clôture de ce ticket est bloquée par les tickets suivants
|
||||
issues.dependency.issue_close_blocks=Cette demande d'ajout empêche la clôture des tickets suivants
|
||||
issues.dependency.pr_close_blocks=Cette demande d'ajout empêche la clôture des tickets suivants
|
||||
issues.dependency.issue_close_blocked=Vous devez fermer tous les tickets qui bloquent ce ticket avant de pouvoir le fermer.
|
||||
|
||||
@@ -1179,8 +1179,8 @@ issues.dependency.remove=Rimuovi
|
||||
issues.dependency.remove_info=Rimuovi questa dipendenza
|
||||
issues.dependency.added_dependency=`ha aggiunto una nuova dipendenza %s`
|
||||
issues.dependency.removed_dependency=`ha rimosso una dipendenza %s`
|
||||
issues.dependency.issue_closing_blockedby=La chiusura di questa richiesta pull è bloccata per i seguenti problemi
|
||||
issues.dependency.pr_closing_blockedby=La chiusura di questo problema è bloccata per i seguenti problemi
|
||||
issues.dependency.pr_closing_blockedby=La chiusura di questa richiesta pull è bloccata per i seguenti problemi
|
||||
issues.dependency.issue_closing_blockedby=La chiusura di questo problema è bloccata per i seguenti problemi
|
||||
issues.dependency.issue_close_blocks=Questo problema impedisce la chiusura dei seguenti problemi
|
||||
issues.dependency.pr_close_blocks=Questa richiesta di pull impedisce la chiusura dei seguenti problemi
|
||||
issues.dependency.issue_close_blocked=Devi chiudere tutte le anomalie che bloiccano questo problema prima di chiudelo.
|
||||
|
||||
@@ -1312,8 +1312,8 @@ issues.dependency.remove=削除
|
||||
issues.dependency.remove_info=この依存関係を削除
|
||||
issues.dependency.added_dependency=`が新しい依存関係を追加 %s`
|
||||
issues.dependency.removed_dependency=`が依存関係を削除 %s`
|
||||
issues.dependency.issue_closing_blockedby=このプルリクエストのクローズは、これらの課題によりブロックされています
|
||||
issues.dependency.pr_closing_blockedby=この課題のクローズは、これらの課題によりブロックされています
|
||||
issues.dependency.pr_closing_blockedby=このプルリクエストのクローズは、これらの課題によりブロックされています
|
||||
issues.dependency.issue_closing_blockedby=この課題のクローズは、これらの課題によりブロックされています
|
||||
issues.dependency.issue_close_blocks=この課題は、これらの課題のクローズをブロックしています
|
||||
issues.dependency.pr_close_blocks=このプルリクエストは、これらの課題のクローズをブロックしています
|
||||
issues.dependency.issue_close_blocked=この課題をクローズするには、ブロックしている課題をすべてクローズする必要があります。
|
||||
|
||||
@@ -1326,8 +1326,8 @@ issues.dependency.remove=Noņemt
|
||||
issues.dependency.remove_info=Noņemt šo atkarību
|
||||
issues.dependency.added_dependency=`pievienoja jaunu atkarību %s`
|
||||
issues.dependency.removed_dependency=`noņema atkarību %s`
|
||||
issues.dependency.issue_closing_blockedby=Šī izmaiņu pieprasījuma sapludināšanu bloķē sekojošas problēmas
|
||||
issues.dependency.pr_closing_blockedby=Šīs problēmas aizvēršanu bloķē sekojošas problēmas
|
||||
issues.dependency.pr_closing_blockedby=Šī izmaiņu pieprasījuma sapludināšanu bloķē sekojošas problēmas
|
||||
issues.dependency.issue_closing_blockedby=Šīs problēmas aizvēršanu bloķē sekojošas problēmas
|
||||
issues.dependency.issue_close_blocks=Šī problēma bloķē sekojošu problēmu aizvēršanu
|
||||
issues.dependency.pr_close_blocks=Šis izmaiņu pieprasījums bloķē sekojošu problēmu aizvēršanu
|
||||
issues.dependency.issue_close_blocked=Nepieciešams aizvērt visas problēmas, kas bloķē šo problēmu, lai to varētu aizērt.
|
||||
|
||||
@@ -738,8 +738,8 @@ issues.deleted_milestone=`(ഇല്ലാതാക്കി)`
|
||||
issues.filter_type.all_issues=എല്ലാ ഇഷ്യൂകളും
|
||||
issues.label_open_issues=%d തുറന്നനിലയിലുള്ള ഇഷ്യൂകള്
|
||||
issues.label_deletion_desc=ഒരു ലേബൽ ഇല്ലാതാക്കിയാല്, അതു് നിയുകതമാക്കിയ എല്ലാ ഇഷ്യൂകളില് നിന്നും നീക്കംചെയ്യും. തുടരട്ടെ?
|
||||
issues.dependency.issue_closing_blockedby=ഈ ലയന അഭ്യര്ത്ഥന അടയ്ക്കുന്നത് ഇനിപ്പറയുന്ന ഇഷ്യൂകള് തടയുന്നു്
|
||||
issues.dependency.pr_closing_blockedby=ഈ ഇഷ്യു അടയ്ക്കുന്നത് ഇനിപ്പറയുന്ന ലയന അഭ്യര്ത്ഥന തടയുന്നു്
|
||||
issues.dependency.pr_closing_blockedby=ഈ ലയന അഭ്യര്ത്ഥന അടയ്ക്കുന്നത് ഇനിപ്പറയുന്ന ഇഷ്യൂകള് തടയുന്നു്
|
||||
issues.dependency.issue_closing_blockedby=ഈ ഇഷ്യു അടയ്ക്കുന്നത് ഇനിപ്പറയുന്ന ലയന അഭ്യര്ത്ഥന തടയുന്നു്
|
||||
issues.dependency.issue_close_blocks=ഈ ഇഷ്യു അടയ്ക്കുന്നത് ഇനിപ്പറയുന്ന ഇഷ്യൂകള് തടയുന്നു്
|
||||
issues.dependency.pr_close_blocks=ഈ ഇഷ്യൂകള് അടയ്ക്കുന്നത് ഈ ലയന അഭ്യര്ത്ഥന തടയുന്നു്
|
||||
issues.dependency.issue_close_blocked=ഈ ഇഷ്യൂ അടയ്ക്കുന്നതിന് മുമ്പ് ഇതിനെ തടയുന്ന എല്ലാ ഇഷ്യൂകളും നിങ്ങൾ അടയ്ക്കേണ്ടതുണ്ട്.
|
||||
|
||||
@@ -1168,8 +1168,8 @@ issues.dependency.remove=Verwijder
|
||||
issues.dependency.remove_info=Verwijder afhankelijkheid
|
||||
issues.dependency.added_dependency=`voegde een nieuwe afhankelijkheid %s toe `
|
||||
issues.dependency.removed_dependency=`verwijderde een afhankelijkheid %s`
|
||||
issues.dependency.issue_closing_blockedby=Het sluiten van deze pull-aanvraag is geblokkeerd door de volgende kwesties
|
||||
issues.dependency.pr_closing_blockedby=Het sluiten van deze kwestie is geblokkeerd door de volgende kwesties
|
||||
issues.dependency.pr_closing_blockedby=Het sluiten van deze pull-aanvraag is geblokkeerd door de volgende kwesties
|
||||
issues.dependency.issue_closing_blockedby=Het sluiten van deze kwestie is geblokkeerd door de volgende kwesties
|
||||
issues.dependency.issue_close_blocks=Deze kwestie blokkeert het sluiten van de volgende kwesties
|
||||
issues.dependency.pr_close_blocks=Deze pull-aanvraag blokkeert het sluiten van de volgende kwesties
|
||||
issues.dependency.issue_close_blocked=Je moet alle kwesties die deze kwestie blokkeren sluiten voordat je deze kan sluiten.
|
||||
|
||||
@@ -1092,8 +1092,8 @@ issues.dependency.remove=Usuń
|
||||
issues.dependency.remove_info=Usuń tę zależność
|
||||
issues.dependency.added_dependency=`dodał nową zależność %s`
|
||||
issues.dependency.removed_dependency=`usunął zależność %s`
|
||||
issues.dependency.issue_closing_blockedby=Zamknięcie tego Pull Requesta jest blokowane przez następujące zgłoszenia
|
||||
issues.dependency.pr_closing_blockedby=Zamknięcie tego zgłoszenia jest blokowane przez następujące zgłoszenia
|
||||
issues.dependency.pr_closing_blockedby=Zamknięcie tego Pull Requesta jest blokowane przez następujące zgłoszenia
|
||||
issues.dependency.issue_closing_blockedby=Zamknięcie tego zgłoszenia jest blokowane przez następujące zgłoszenia
|
||||
issues.dependency.issue_close_blocks=To zgłoszenie blokuje zamknięcie następujących zgłoszeń
|
||||
issues.dependency.pr_close_blocks=Ten Pull Request blokuje zamknięcie następujących zgłoszeń
|
||||
issues.dependency.issue_close_blocked=Musisz zamknąć wszystkie zgłoszenia blokujące to zgłoszenie zanim je zamkniesz.
|
||||
|
||||
@@ -1186,8 +1186,8 @@ issues.dependency.add=Adicione…
|
||||
issues.dependency.cancel=Cancelar
|
||||
issues.dependency.remove=Remover
|
||||
issues.dependency.remove_info=Remover esta dependência
|
||||
issues.dependency.issue_closing_blockedby=Fechamento deste pull request está bloqueado pelas seguintes issues
|
||||
issues.dependency.pr_closing_blockedby=Fechamento desta issue está bloqueado pelas seguintes issues
|
||||
issues.dependency.pr_closing_blockedby=Fechamento deste pull request está bloqueado pelas seguintes issues
|
||||
issues.dependency.issue_closing_blockedby=Fechamento desta issue está bloqueado pelas seguintes issues
|
||||
issues.dependency.issue_close_blocks=Esta issue bloqueia o fechamento das seguintes issues
|
||||
issues.dependency.pr_close_blocks=Este pull request bloqueia o fechamento das seguintes issues
|
||||
issues.dependency.issue_close_blocked=Você precisa fechar todas as issues que bloqueiam esta issue antes de poder fechá-la.
|
||||
|
||||
@@ -1326,8 +1326,8 @@ issues.dependency.remove=Remover
|
||||
issues.dependency.remove_info=Remover esta dependência
|
||||
issues.dependency.added_dependency=`adicionou uma nova dependência %s`
|
||||
issues.dependency.removed_dependency=`removeu uma dependência %s`
|
||||
issues.dependency.issue_closing_blockedby=O encerramento deste pedido de integração está bloqueado pelas seguintes questões
|
||||
issues.dependency.pr_closing_blockedby=O encerramento desta questão está bloqueado pelas seguintes questões
|
||||
issues.dependency.pr_closing_blockedby=O encerramento deste pedido de integração está bloqueado pelas seguintes questões
|
||||
issues.dependency.issue_closing_blockedby=O encerramento desta questão está bloqueado pelas seguintes questões
|
||||
issues.dependency.issue_close_blocks=Esta questão bloqueia o encerramento das seguintes questões
|
||||
issues.dependency.pr_close_blocks=Este pedido de integração bloqueia o encerramento das seguintes questões
|
||||
issues.dependency.issue_close_blocked=Tem que encerrar todas as questões que bloqueiam esta questão antes de a poder encerrar.
|
||||
|
||||
@@ -1324,8 +1324,8 @@ issues.dependency.remove=Удалить
|
||||
issues.dependency.remove_info=Удалить эту зависимость
|
||||
issues.dependency.added_dependency=`добавить новую зависимость %s`
|
||||
issues.dependency.removed_dependency=`убрал зависимость %s`
|
||||
issues.dependency.issue_closing_blockedby=Закрытие этого запроса на слияние невозможно до закрытия следующих задач
|
||||
issues.dependency.pr_closing_blockedby=Закрытие этой задачи блокируется следующими задачами
|
||||
issues.dependency.pr_closing_blockedby=Закрытие этого запроса на слияние невозможно до закрытия следующих задач
|
||||
issues.dependency.issue_closing_blockedby=Закрытие этой задачи блокируется следующими задачами
|
||||
issues.dependency.issue_close_blocks=Эта задача блокирует закрытие следующих задач
|
||||
issues.dependency.pr_close_blocks=Этот запрос на слияние блокирует закрытие следующих задач
|
||||
issues.dependency.issue_close_blocked=Вам необходимо закрыть все задачи, блокирующие эту задачу, прежде чем вы сможете её закрыть.
|
||||
|
||||
@@ -1121,8 +1121,8 @@ issues.dependency.remove=Ta bort
|
||||
issues.dependency.remove_info=Ta bort detta beroende
|
||||
issues.dependency.added_dependency=`lade till ett nytt beroende %s`
|
||||
issues.dependency.removed_dependency=`tog bort ett beroende %s`
|
||||
issues.dependency.issue_closing_blockedby=En stängning av denna pull-förfrågan blockeras av följande ärenden
|
||||
issues.dependency.pr_closing_blockedby=En stängning av ärendet blockeras av följande ärenden
|
||||
issues.dependency.pr_closing_blockedby=En stängning av denna pull-förfrågan blockeras av följande ärenden
|
||||
issues.dependency.issue_closing_blockedby=En stängning av ärendet blockeras av följande ärenden
|
||||
issues.dependency.issue_close_blocks=Detta ärende blockerar en stängning av följande ärenden
|
||||
issues.dependency.pr_close_blocks=Denna pull-förfrågan blockerar stängning av följande ärenden
|
||||
issues.dependency.issue_close_blocked=Du måste stänga alla ärenden som blockerar det här ärendet innan du kan stänga det.
|
||||
|
||||
@@ -1252,8 +1252,8 @@ issues.dependency.remove=Kaldır
|
||||
issues.dependency.remove_info=Bu bağımlılığı kaldır
|
||||
issues.dependency.added_dependency=`yeni bir %s bağımlılığı eklendi`
|
||||
issues.dependency.removed_dependency=`bir %s bağımlılığı kaldırıldı`
|
||||
issues.dependency.issue_closing_blockedby=Bu değişiklik isteğinin kapatılması aşağıdaki konular nedeniyle engelleniyor
|
||||
issues.dependency.pr_closing_blockedby=Bu konunun kapatılması aşağıdaki konular tarafından engelleniyor
|
||||
issues.dependency.pr_closing_blockedby=Bu değişiklik isteğinin kapatılması aşağıdaki konular nedeniyle engelleniyor
|
||||
issues.dependency.issue_closing_blockedby=Bu konunun kapatılması aşağıdaki konular tarafından engelleniyor
|
||||
issues.dependency.issue_close_blocks=Bu konu aşağıdaki konuların kapatılmasını engelliyor
|
||||
issues.dependency.pr_close_blocks=Bu değişiklik isteği aşağıdaki sorunların kapatılmasını engelliyor
|
||||
issues.dependency.issue_close_blocked=Kapatmadan önce bu konuyu engelleyen tüm konuları kapatmanız gerekir.
|
||||
|
||||
@@ -1306,8 +1306,8 @@ issues.dependency.remove=Видалити
|
||||
issues.dependency.remove_info=Видалити цю залежність
|
||||
issues.dependency.added_dependency=`додав нову залежність %s`
|
||||
issues.dependency.removed_dependency=`видалив залежність %s`
|
||||
issues.dependency.issue_closing_blockedby=Закриття цього запиту на злиття заблокує наступні проблеми
|
||||
issues.dependency.pr_closing_blockedby=Закриття цієї проблеми заблокує наступні проблеми
|
||||
issues.dependency.pr_closing_blockedby=Закриття цього запиту на злиття заблокує наступні проблеми
|
||||
issues.dependency.issue_closing_blockedby=Закриття цієї проблеми заблокує наступні проблеми
|
||||
issues.dependency.issue_close_blocks=Ця проблема блокує закриття залежних проблем
|
||||
issues.dependency.pr_close_blocks=Цей пулл-реквест блокує закриття залежних проблем
|
||||
issues.dependency.issue_close_blocked=Вам потрібно закрити всі проблеми, що блокують цю проблему, перед її закриттям.
|
||||
|
||||
@@ -1322,8 +1322,8 @@ issues.dependency.remove=删除
|
||||
issues.dependency.remove_info=删除此依赖项
|
||||
issues.dependency.added_dependency=`添加了一个新的依赖项 %s`
|
||||
issues.dependency.removed_dependency=`移除了一个依赖项 %s`
|
||||
issues.dependency.issue_closing_blockedby=以下工单阻止了关闭此合并请求
|
||||
issues.dependency.pr_closing_blockedby=以下工单阻止了关闭此工单
|
||||
issues.dependency.pr_closing_blockedby=以下工单阻止了关闭此合并请求
|
||||
issues.dependency.issue_closing_blockedby=以下工单阻止了关闭此工单
|
||||
issues.dependency.issue_close_blocks=此工单阻止了以下工单的关闭
|
||||
issues.dependency.pr_close_blocks=此合并请求阻止以下工单的关闭
|
||||
issues.dependency.issue_close_blocked=您需要关闭所有阻止此工单的工单, 然后才能关闭它。
|
||||
|
||||
@@ -1311,8 +1311,8 @@ issues.dependency.remove=移除
|
||||
issues.dependency.remove_info=移除此先決條件
|
||||
issues.dependency.added_dependency=`加入了新的先決條件 %s`
|
||||
issues.dependency.removed_dependency=`移除了先決條件 %s`
|
||||
issues.dependency.issue_closing_blockedby=此合併請求被下列問題阻擋而無法關閉
|
||||
issues.dependency.pr_closing_blockedby=此問題被下列問題阻擋而無法關閉
|
||||
issues.dependency.pr_closing_blockedby=此合併請求被下列問題阻擋而無法關閉
|
||||
issues.dependency.issue_closing_blockedby=此問題被下列問題阻擋而無法關閉
|
||||
issues.dependency.issue_close_blocks=因為此問題的阻擋,下列問題無法被關閉
|
||||
issues.dependency.pr_close_blocks=因為此合併請求的阻擋,下列問題無法被關閉
|
||||
issues.dependency.issue_close_blocked=在您關閉此問題以前,您必須先關閉所有阻擋它的問題。
|
||||
|
||||
Generated
+6
-6
@@ -12076,9 +12076,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
|
||||
"integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
|
||||
"version": "6.1.6",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz",
|
||||
"integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
@@ -23018,9 +23018,9 @@
|
||||
"integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw=="
|
||||
},
|
||||
"tar": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
|
||||
"integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
|
||||
"version": "6.1.6",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz",
|
||||
"integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chownr": "^2.0.0",
|
||||
|
||||
@@ -569,6 +569,7 @@ func Routes() *web.Route {
|
||||
//setting.CORSConfig.AllowSubdomain // FIXME: the cors middleware needs allowSubdomain option
|
||||
AllowedMethods: setting.CORSConfig.Methods,
|
||||
AllowCredentials: setting.CORSConfig.AllowCredentials,
|
||||
AllowedHeaders: []string{"Authorization", "X-CSRFToken", "X-Gitea-OTP"},
|
||||
MaxAge: int(setting.CORSConfig.MaxAge.Seconds()),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1254,5 +1254,6 @@ func GetPullRequestCommits(ctx *context.APIContext) {
|
||||
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", totalNumberOfCommits))
|
||||
ctx.Header().Set("X-PageCount", strconv.Itoa(totalNumberOfPages))
|
||||
ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < totalNumberOfPages))
|
||||
ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, X-PerPage, X-Total, X-PageCount, X-HasMore, Link")
|
||||
ctx.JSON(http.StatusOK, &apiCommits)
|
||||
}
|
||||
|
||||
@@ -14,3 +14,10 @@ type swaggerResponseOAuth2Application struct {
|
||||
// in:body
|
||||
Body api.OAuth2Application `json:"body"`
|
||||
}
|
||||
|
||||
// AccessToken represents an API access token.
|
||||
// swagger:response AccessToken
|
||||
type swaggerResponseAccessToken struct {
|
||||
// in:body
|
||||
Body api.AccessToken `json:"body"`
|
||||
}
|
||||
|
||||
@@ -164,6 +164,9 @@ type swaggerParameterBodies struct {
|
||||
// in:body
|
||||
CreateTagOption api.CreateTagOption
|
||||
|
||||
// in:body
|
||||
CreateAccessTokenOption api.CreateAccessTokenOption
|
||||
|
||||
// in:body
|
||||
UserSettingsOptions api.UserSettingsOptions
|
||||
}
|
||||
|
||||
@@ -76,15 +76,10 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||
// description: username of user
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: accessToken
|
||||
// - name: userCreateToken
|
||||
// in: body
|
||||
// schema:
|
||||
// type: object
|
||||
// required:
|
||||
// - name
|
||||
// properties:
|
||||
// name:
|
||||
// type: string
|
||||
// "$ref": "#/definitions/CreateAccessTokenOption"
|
||||
// responses:
|
||||
// "201":
|
||||
// "$ref": "#/responses/AccessToken"
|
||||
|
||||
@@ -392,11 +392,6 @@ func HookPreReceive(ctx *gitea_context.PrivateContext) {
|
||||
})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
log.Error("Unexpected ref: %s", refFullName)
|
||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||
Err: fmt.Sprintf("Unexpected ref: %s", refFullName),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/upload"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/gitdiff"
|
||||
)
|
||||
|
||||
@@ -567,6 +568,18 @@ func PrepareCompareDiff(
|
||||
} else {
|
||||
title = headBranch
|
||||
}
|
||||
if len(title) > 255 {
|
||||
var trailer string
|
||||
title, trailer = util.SplitStringAtByteN(title, 255)
|
||||
if len(trailer) > 0 {
|
||||
if ctx.Data["content"] != nil {
|
||||
ctx.Data["content"] = fmt.Sprintf("%s\n\n%s", trailer, ctx.Data["content"])
|
||||
} else {
|
||||
ctx.Data["content"] = trailer + "\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Data["title"] = title
|
||||
ctx.Data["Username"] = headUser.Name
|
||||
ctx.Data["Reponame"] = headRepo.Name
|
||||
|
||||
+19
-15
@@ -1728,10 +1728,12 @@ func UpdateIssueContent(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
files := ctx.QueryStrings("files[]")
|
||||
if err := updateAttachments(issue, files); err != nil {
|
||||
ctx.ServerError("UpdateAttachments", err)
|
||||
return
|
||||
// when update the request doesn't intend to update attachments (eg: change checkbox state), ignore attachment updates
|
||||
if !ctx.QueryBool("ignore_attachments") {
|
||||
if err := updateAttachments(issue, ctx.QueryStrings("files[]")); err != nil {
|
||||
ctx.ServerError("UpdateAttachments", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
content, err := markdown.RenderString(&markup.RenderContext{
|
||||
@@ -2128,13 +2130,6 @@ func UpdateCommentContent(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if comment.Type == models.CommentTypeComment {
|
||||
if err := comment.LoadAttachments(); err != nil {
|
||||
ctx.ServerError("LoadAttachments", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
|
||||
ctx.Error(http.StatusForbidden)
|
||||
return
|
||||
@@ -2156,10 +2151,19 @@ func UpdateCommentContent(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
files := ctx.QueryStrings("files[]")
|
||||
if err := updateAttachments(comment, files); err != nil {
|
||||
ctx.ServerError("UpdateAttachments", err)
|
||||
return
|
||||
if comment.Type == models.CommentTypeComment {
|
||||
if err := comment.LoadAttachments(); err != nil {
|
||||
ctx.ServerError("LoadAttachments", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// when the update request doesn't intend to update attachments (eg: change checkbox state), ignore attachment updates
|
||||
if !ctx.QueryBool("ignore_attachments") {
|
||||
if err := updateAttachments(comment, ctx.QueryStrings("files[]")); err != nil {
|
||||
ctx.ServerError("UpdateAttachments", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
content, err := markdown.RenderString(&markup.RenderContext{
|
||||
|
||||
@@ -1001,10 +1001,14 @@ func CompareAndPullRequestPost(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes")
|
||||
ctx.Data["PageIsComparePull"] = true
|
||||
ctx.Data["IsDiffCompare"] = true
|
||||
ctx.Data["IsRepoToolbarCommits"] = true
|
||||
ctx.Data["RequireTribute"] = true
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
|
||||
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
|
||||
upload.AddUploadContext(ctx, "comment")
|
||||
ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWrite(models.UnitTypePullRequests)
|
||||
|
||||
var (
|
||||
repo = ctx.Repo.Repository
|
||||
@@ -1037,6 +1041,14 @@ func CompareAndPullRequestPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Title) > 255 {
|
||||
var trailer string
|
||||
form.Title, trailer = util.SplitStringAtByteN(form.Title, 255)
|
||||
|
||||
form.Content = trailer + "\n\n" + form.Content
|
||||
}
|
||||
middleware.AssignForm(form, ctx.Data)
|
||||
|
||||
ctx.HTML(http.StatusOK, tplCompareDiff)
|
||||
return
|
||||
}
|
||||
|
||||
+11
-11
@@ -24,7 +24,7 @@ import (
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/golang-jwt/jwt"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
@@ -187,7 +187,7 @@ func newAccessTokenResponse(grant *models.OAuth2Grant, signingKey oauth2.JWTSign
|
||||
ErrorDescription: "cannot find application",
|
||||
}
|
||||
}
|
||||
err = app.LoadUser()
|
||||
user, err := models.GetUserByID(grant.UserID)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
return nil, &AccessTokenError{
|
||||
@@ -212,17 +212,17 @@ func newAccessTokenResponse(grant *models.OAuth2Grant, signingKey oauth2.JWTSign
|
||||
Nonce: grant.Nonce,
|
||||
}
|
||||
if grant.ScopeContains("profile") {
|
||||
idToken.Name = app.User.FullName
|
||||
idToken.PreferredUsername = app.User.Name
|
||||
idToken.Profile = app.User.HTMLURL()
|
||||
idToken.Picture = app.User.AvatarLink()
|
||||
idToken.Website = app.User.Website
|
||||
idToken.Locale = app.User.Language
|
||||
idToken.UpdatedAt = app.User.UpdatedUnix
|
||||
idToken.Name = user.FullName
|
||||
idToken.PreferredUsername = user.Name
|
||||
idToken.Profile = user.HTMLURL()
|
||||
idToken.Picture = user.AvatarLink()
|
||||
idToken.Website = user.Website
|
||||
idToken.Locale = user.Language
|
||||
idToken.UpdatedAt = user.UpdatedUnix
|
||||
}
|
||||
if grant.ScopeContains("email") {
|
||||
idToken.Email = app.User.Email
|
||||
idToken.EmailVerified = app.User.IsActive
|
||||
idToken.Email = user.Email
|
||||
idToken.EmailVerified = user.IsActive
|
||||
}
|
||||
|
||||
signedIDToken, err = idToken.SignToken(signingKey)
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// 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 user
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth/oauth2"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func createAndParseToken(t *testing.T, grant *models.OAuth2Grant) *models.OIDCToken {
|
||||
signingKey, err := oauth2.CreateJWTSingingKey("HS256", make([]byte, 32))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, signingKey)
|
||||
oauth2.DefaultSigningKey = signingKey
|
||||
|
||||
response, terr := newAccessTokenResponse(grant, signingKey)
|
||||
assert.Nil(t, terr)
|
||||
assert.NotNil(t, response)
|
||||
|
||||
parsedToken, err := jwt.ParseWithClaims(response.IDToken, &models.OIDCToken{}, func(token *jwt.Token) (interface{}, error) {
|
||||
assert.NotNil(t, token.Method)
|
||||
assert.Equal(t, signingKey.SigningMethod().Alg(), token.Method.Alg())
|
||||
return signingKey.VerifyKey(), nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, parsedToken.Valid)
|
||||
|
||||
oidcToken, ok := parsedToken.Claims.(*models.OIDCToken)
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, oidcToken)
|
||||
|
||||
return oidcToken
|
||||
}
|
||||
|
||||
func TestNewAccessTokenResponse_OIDCToken(t *testing.T) {
|
||||
assert.NoError(t, models.PrepareTestDatabase())
|
||||
|
||||
grants, err := models.GetOAuth2GrantsByUserID(3)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, grants, 1)
|
||||
|
||||
// Scopes: openid
|
||||
oidcToken := createAndParseToken(t, grants[0])
|
||||
assert.Empty(t, oidcToken.Name)
|
||||
assert.Empty(t, oidcToken.PreferredUsername)
|
||||
assert.Empty(t, oidcToken.Profile)
|
||||
assert.Empty(t, oidcToken.Picture)
|
||||
assert.Empty(t, oidcToken.Website)
|
||||
assert.Empty(t, oidcToken.UpdatedAt)
|
||||
assert.Empty(t, oidcToken.Email)
|
||||
assert.False(t, oidcToken.EmailVerified)
|
||||
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 5}).(*models.User)
|
||||
grants, err = models.GetOAuth2GrantsByUserID(user.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, grants, 1)
|
||||
|
||||
// Scopes: openid profile email
|
||||
oidcToken = createAndParseToken(t, grants[0])
|
||||
assert.Equal(t, user.FullName, oidcToken.Name)
|
||||
assert.Equal(t, user.Name, oidcToken.PreferredUsername)
|
||||
assert.Equal(t, user.HTMLURL(), oidcToken.Profile)
|
||||
assert.Equal(t, user.AvatarLink(), oidcToken.Picture)
|
||||
assert.Equal(t, user.Website, oidcToken.Website)
|
||||
assert.Equal(t, user.UpdatedUnix, oidcToken.UpdatedAt)
|
||||
assert.Equal(t, user.Email, oidcToken.Email)
|
||||
assert.Equal(t, user.IsActive, oidcToken.EmailVerified)
|
||||
}
|
||||
+6
-1
@@ -822,9 +822,14 @@ func RegisterRoutes(m *web.Route) {
|
||||
}
|
||||
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
|
||||
})
|
||||
m.Get("/attachments/{uuid}", repo.GetAttachment)
|
||||
|
||||
}, ignSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoReleaseReader)
|
||||
|
||||
// to maintain compatibility with old attachments
|
||||
m.Group("/{username}/{reponame}", func() {
|
||||
m.Get("/attachments/{uuid}", repo.GetAttachment)
|
||||
}, ignSignIn, context.RepoAssignment, context.UnitTypes())
|
||||
|
||||
m.Group("/{username}/{reponame}", func() {
|
||||
m.Post("/topics", repo.TopicsPost)
|
||||
}, context.RepoAssignment, context.RepoMustNotBeArchived(), reqRepoAdmin)
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/golang-jwt/jwt"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
|
||||
@@ -90,6 +90,9 @@ func prepareWikiFileName(gitRepo *git.Repository, wikiName string) (bool, string
|
||||
// Look for both files
|
||||
filesInIndex, err := gitRepo.LsTree("master", unescaped, escaped)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Not a valid object name master") {
|
||||
return false, escaped, nil
|
||||
}
|
||||
log.Error("%v", err)
|
||||
return false, escaped, err
|
||||
}
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
package wiki
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -261,3 +265,28 @@ func TestPrepareWikiFileName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareWikiFileName_FirstPage(t *testing.T) {
|
||||
models.PrepareTestEnv(t)
|
||||
|
||||
// Now create a temporaryDirectory
|
||||
tmpDir, err := ioutil.TempDir("", "empty-wiki")
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
if _, err := os.Stat(tmpDir); !os.IsNotExist(err) {
|
||||
_ = util.RemoveAll(tmpDir)
|
||||
}
|
||||
}()
|
||||
|
||||
err = git.InitRepository(tmpDir, true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
gitRepo, err := git.OpenRepository(tmpDir)
|
||||
defer gitRepo.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
existence, newWikiPath, err := prepareWikiFileName(gitRepo, "Home")
|
||||
assert.False(t, existence)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Home.md", newWikiPath)
|
||||
}
|
||||
|
||||
@@ -176,10 +176,10 @@
|
||||
{{if .IsNothingToCompare}}
|
||||
{{if and $.IsSigned $.AllowEmptyPr (not .Repository.IsArchived) }}
|
||||
<div class="ui segment">{{.i18n.Tr "repo.pulls.nothing_to_compare_and_allow_empty_pr"}}</div>
|
||||
<div class="ui info message show-form-container">
|
||||
<div class="ui info message show-form-container" {{if .Flash}}style="display: none"{{end}}>
|
||||
<button class="ui button green show-form">{{.i18n.Tr "repo.pulls.new"}}</button>
|
||||
</div>
|
||||
<div class="pullrequest-form" style="display: none">
|
||||
<div class="pullrequest-form" {{if not .Flash}}style="display: none"{{end}}>
|
||||
{{template "repo/issue/new_form" .}}
|
||||
</div>
|
||||
{{else}}
|
||||
@@ -192,7 +192,7 @@
|
||||
</div>
|
||||
{{else}}
|
||||
{{if and $.IsSigned (not .Repository.IsArchived)}}
|
||||
<div class="ui info message show-form-container">
|
||||
<div class="ui info message show-form-container" {{if .Flash}}style="display: none"{{end}}>
|
||||
<button class="ui button green show-form">{{.i18n.Tr "repo.pulls.new"}}</button>
|
||||
</div>
|
||||
{{else if .Repository.IsArchived}}
|
||||
@@ -201,7 +201,7 @@
|
||||
</div>
|
||||
{{end}}
|
||||
{{if $.IsSigned}}
|
||||
<div class="pullrequest-form" style="display: none">
|
||||
<div class="pullrequest-form" {{if not .Flash}}style="display: none"{{end}}>
|
||||
{{template "repo/issue/new_form" .}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -82,7 +82,9 @@
|
||||
<a class="mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a>
|
||||
</span>
|
||||
{{end}}
|
||||
{{template "repo/branch_dropdown" dict "root" $ "release" .}}
|
||||
{{if .Sha1 }}
|
||||
{{template "repo/branch_dropdown" dict "root" $ "release" .}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui twelve wide column detail">
|
||||
|
||||
@@ -11917,18 +11917,10 @@
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "accessToken",
|
||||
"name": "userCreateToken",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
"$ref": "#/definitions/CreateAccessTokenOption"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -12654,6 +12646,17 @@
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||
},
|
||||
"CreateAccessTokenOption": {
|
||||
"description": "CreateAccessTokenOption options when create access token",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"x-go-name": "Name"
|
||||
}
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||
},
|
||||
"CreateBranchProtectionOption": {
|
||||
"description": "CreateBranchProtectionOption options for creating a branch protection",
|
||||
"type": "object",
|
||||
@@ -17044,20 +17047,8 @@
|
||||
"responses": {
|
||||
"AccessToken": {
|
||||
"description": "AccessToken represents an API access token.",
|
||||
"headers": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"sha1": {
|
||||
"type": "string"
|
||||
},
|
||||
"token_last_eight": {
|
||||
"type": "string"
|
||||
}
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AccessToken"
|
||||
}
|
||||
},
|
||||
"AccessTokenList": {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/markdown"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
// Contains fuzzing functions executed by
|
||||
@@ -32,6 +33,7 @@ var (
|
||||
)
|
||||
|
||||
func FuzzMarkdownRenderRaw(data []byte) int {
|
||||
setting.AppURL = "http://localhost:3000/"
|
||||
err := markdown.RenderRaw(&renderContext, bytes.NewReader(data), io.Discard)
|
||||
if err != nil {
|
||||
return 0
|
||||
@@ -40,6 +42,7 @@ func FuzzMarkdownRenderRaw(data []byte) int {
|
||||
}
|
||||
|
||||
func FuzzMarkupPostProcess(data []byte) int {
|
||||
setting.AppURL = "http://localhost:3000/"
|
||||
err := markup.PostProcess(&renderContext, bytes.NewReader(data), io.Discard)
|
||||
if err != nil {
|
||||
return 0
|
||||
|
||||
+7
-2
@@ -21,8 +21,8 @@ const (
|
||||
// Queue defines a queue struct
|
||||
type Queue struct {
|
||||
db *leveldb.DB
|
||||
highLock sync.Mutex
|
||||
lowLock sync.Mutex
|
||||
lowLock sync.Mutex // If you are locking both high and low locks, lock the low lock before the high lock
|
||||
highLock sync.Mutex // If you are locking both high and low locks, lock the low lock before the high lock
|
||||
low int64
|
||||
high int64
|
||||
lowKey []byte
|
||||
@@ -295,6 +295,11 @@ func (queue *Queue) LHandle(h func([]byte) error) error {
|
||||
|
||||
// Close closes the queue (and the underlying db is set to closeUnderlyingDB)
|
||||
func (queue *Queue) Close() error {
|
||||
queue.lowLock.Lock()
|
||||
queue.highLock.Lock()
|
||||
defer queue.lowLock.Unlock()
|
||||
defer queue.highLock.Unlock()
|
||||
|
||||
if !queue.closeUnderlyingDB {
|
||||
queue.db = nil
|
||||
return nil
|
||||
|
||||
+2
@@ -107,6 +107,8 @@ func (set *Set) Remove(value []byte) (bool, error) {
|
||||
|
||||
// Close closes the set (and the underlying db if set to closeUnderlyingDB)
|
||||
func (set *Set) Close() error {
|
||||
set.lock.Lock()
|
||||
defer set.lock.Unlock()
|
||||
if !set.closeUnderlyingDB {
|
||||
set.db = nil
|
||||
return nil
|
||||
|
||||
+2
@@ -181,6 +181,8 @@ func (queue *UniqueQueue) Len() int64 {
|
||||
func (queue *UniqueQueue) Close() error {
|
||||
_ = queue.q.Close()
|
||||
_ = queue.set.Close()
|
||||
queue.set.lock.Lock()
|
||||
defer queue.set.lock.Unlock()
|
||||
if !queue.closeUnderlyingDB {
|
||||
queue.db = nil
|
||||
return nil
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
language: go
|
||||
|
||||
script:
|
||||
- go vet ./...
|
||||
- go test -v ./...
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- tip
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
## Migration Guide from v2 -> v3
|
||||
|
||||
Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code.
|
||||
|
||||
### `Token.Claims` is now an interface type
|
||||
|
||||
The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`.
|
||||
|
||||
`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property.
|
||||
|
||||
The old example for parsing a token looked like this..
|
||||
|
||||
```go
|
||||
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
|
||||
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
is now directly mapped to...
|
||||
|
||||
```go
|
||||
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type.
|
||||
|
||||
```go
|
||||
type MyCustomClaims struct {
|
||||
User string
|
||||
*StandardClaims
|
||||
}
|
||||
|
||||
if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil {
|
||||
claims := token.Claims.(*MyCustomClaims)
|
||||
fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt)
|
||||
}
|
||||
```
|
||||
|
||||
### `ParseFromRequest` has been moved
|
||||
|
||||
To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`.
|
||||
|
||||
`Extractors` do the work of picking the token string out of a request. The interface is simple and composable.
|
||||
|
||||
This simple parsing example:
|
||||
|
||||
```go
|
||||
if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil {
|
||||
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
is directly mapped to:
|
||||
|
||||
```go
|
||||
if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil {
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
|
||||
}
|
||||
```
|
||||
|
||||
There are several concrete `Extractor` types provided for your convenience:
|
||||
|
||||
* `HeaderExtractor` will search a list of headers until one contains content.
|
||||
* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content.
|
||||
* `MultiExtractor` will try a list of `Extractors` in order until one returns content.
|
||||
* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token.
|
||||
* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument
|
||||
* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header
|
||||
|
||||
|
||||
### RSA signing methods no longer accept `[]byte` keys
|
||||
|
||||
Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse.
|
||||
|
||||
To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types.
|
||||
|
||||
```go
|
||||
func keyLookupFunc(*Token) (interface{}, error) {
|
||||
// Don't forget to validate the alg is what you expect:
|
||||
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
|
||||
// Look up key
|
||||
key, err := lookupPublicKey(token.Header["kid"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unpack key from PEM encoded PKCS8
|
||||
return jwt.ParseRSAPublicKeyFromPEM(key)
|
||||
}
|
||||
```
|
||||
Generated
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
.DS_Store
|
||||
bin
|
||||
|
||||
.idea/
|
||||
|
||||
Generated
Vendored
+1
@@ -1,4 +1,5 @@
|
||||
Copyright (c) 2012 Dave Grijalva
|
||||
Copyright (c) 2021 golang-jwt maintainers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
## Migration Guide (v3.2.1)
|
||||
|
||||
Starting from [v3.2.1](https://github.com/golang-jwt/jwt/releases/tag/v3.2.1]), the import path has changed from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`. Future releases will be using the `github.com/golang-jwt/jwt` import path and continue the existing versioning scheme of `v3.x.x+incompatible`. Backwards-compatible patches and fixes will be done on the `v3` release branch, where as new build-breaking features will be developed in a `v4` release, possibly including a SIV-style import path.
|
||||
|
||||
### go.mod replacement
|
||||
|
||||
In a first step, the easiest way is to use `go mod edit` to issue a replacement.
|
||||
|
||||
```
|
||||
go mod edit -replace github.com/dgrijalva/jwt-go=github.com/golang-jwt/jwt@v3.2.1+incompatible
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
This will still keep the old import path in your code but replace it with the new package and also introduce a new indirect dependency to `github.com/golang-jwt/jwt`. Try to compile your project; it should still work.
|
||||
|
||||
### Cleanup
|
||||
|
||||
If your code still consistently builds, you can replace all occurences of `github.com/dgrijalva/jwt-go` with `github.com/golang-jwt/jwt`, either manually or by using tools such as `sed`. Finally, the `replace` directive in the `go.mod` file can be removed.
|
||||
|
||||
## Older releases (before v3.2.0)
|
||||
|
||||
The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md.
|
||||
Generated
Vendored
+34
-21
@@ -1,25 +1,34 @@
|
||||
# jwt-go
|
||||
|
||||
[](https://travis-ci.org/dgrijalva/jwt-go)
|
||||
[](https://godoc.org/github.com/dgrijalva/jwt-go)
|
||||
[](https://github.com/golang-jwt/jwt/actions/workflows/build.yml)
|
||||
[](https://pkg.go.dev/github.com/golang-jwt/jwt)
|
||||
|
||||
A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html)
|
||||
A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519).
|
||||
|
||||
**NEW VERSION COMING:** There have been a lot of improvements suggested since the version 3.0.0 released in 2016. I'm working now on cutting two different releases: 3.2.0 will contain any non-breaking changes or enhancements. 4.0.0 will follow shortly which will include breaking changes. See the 4.0.0 milestone to get an idea of what's coming. If you have other ideas, or would like to participate in 4.0.0, now's the time. If you depend on this library and don't want to be interrupted, I recommend you use your dependency mangement tool to pin to version 3.
|
||||
**IMPORT PATH CHANGE:** Starting from [v3.2.1](https://github.com/golang-jwt/jwt/releases/tag/v3.2.1), the import path has changed from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`. After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic.
|
||||
|
||||
**SECURITY NOTICE:** Some older versions of Go have a security issue in the cryotp/elliptic. Recommendation is to upgrade to at least 1.8.3. See issue #216 for more detail.
|
||||
Future releases will be using the `github.com/golang-jwt/jwt` import path and continue the existing versioning scheme of `v3.x.x+incompatible`. Backwards-compatible patches and fixes will be done on the `v3` release branch, where as new build-breaking features will be developed in a `v4` release, possibly including a SIV-style import path.
|
||||
|
||||
**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided.
|
||||
**SECURITY NOTICE:** Some older versions of Go have a security issue in the crypto/elliptic. Recommendation is to upgrade to at least 1.15 See issue [dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more detail.
|
||||
|
||||
**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided.
|
||||
|
||||
### Supported Go versions
|
||||
|
||||
Our support of Go versions is aligned with Go's [version release policy](https://golang.org/doc/devel/release#policy).
|
||||
So we will support a major version of Go until there are two newer major releases.
|
||||
We no longer support building jwt-go with unsupported Go versions, as these contain security vulnerabilities
|
||||
which will not be fixed.
|
||||
|
||||
## What the heck is a JWT?
|
||||
|
||||
JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens.
|
||||
|
||||
In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way.
|
||||
In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](https://datatracker.ietf.org/doc/html/rfc4648) encoded. The last part is the signature, encoded the same way.
|
||||
|
||||
The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used.
|
||||
|
||||
The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own.
|
||||
The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) for information about reserved keys and the proper way to add your own.
|
||||
|
||||
## What's in the box?
|
||||
|
||||
@@ -27,31 +36,31 @@ This library supports the parsing and verification as well as the generation and
|
||||
|
||||
## Examples
|
||||
|
||||
See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage:
|
||||
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt) for examples of usage:
|
||||
|
||||
* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac)
|
||||
* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac)
|
||||
* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples)
|
||||
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-Parse-Hmac)
|
||||
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-New-Hmac)
|
||||
* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt#pkg-examples)
|
||||
|
||||
## Extensions
|
||||
|
||||
This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`.
|
||||
|
||||
Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go
|
||||
Here's an example of an extension that integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS): https://github.com/someone1/gcp-jwt-go
|
||||
|
||||
## Compliance
|
||||
|
||||
This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences:
|
||||
This library was last reviewed to comply with [RTF 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences:
|
||||
|
||||
* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key.
|
||||
* In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key.
|
||||
|
||||
## Project Status & Versioning
|
||||
|
||||
This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason).
|
||||
|
||||
This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases).
|
||||
This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `main`. Periodically, versions will be tagged from `main`. You can find all the releases on [the project releases page](https://github.com/golang-jwt/jwt/releases).
|
||||
|
||||
While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v3`. It will do the right thing WRT semantic versioning.
|
||||
While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/golang-jwt/jwt.v3`. It will do the right thing WRT semantic versioning.
|
||||
|
||||
**BREAKING CHANGES:***
|
||||
* Version 3.0.0 includes _a lot_ of changes from the 2.x line, including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.
|
||||
@@ -79,9 +88,9 @@ Asymmetric signing methods, such as RSA, use different keys for signing and veri
|
||||
|
||||
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
|
||||
|
||||
* The [HMAC signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
|
||||
* The [RSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
|
||||
* The [ECDSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
|
||||
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
|
||||
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
|
||||
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
|
||||
|
||||
### JWT and OAuth
|
||||
|
||||
@@ -93,8 +102,12 @@ Without going too far down the rabbit hole, here's a description of the interact
|
||||
* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token.
|
||||
* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
This library uses descriptive error messages whenever possible. If you are not getting the expected result, have a look at the errors. The most common place people get stuck is providing the correct type of key to the parser. See the above section on signing methods and key types.
|
||||
|
||||
## More
|
||||
|
||||
Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go).
|
||||
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt).
|
||||
|
||||
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
|
||||
Generated
Vendored
+14
-1
@@ -1,5 +1,18 @@
|
||||
## `jwt-go` Version History
|
||||
|
||||
#### 3.2.2
|
||||
|
||||
* Starting from this release, we are adopting the policy to support the most 2 recent versions of Go currently available. By the time of this release, this is Go 1.15 and 1.16 ([#28](https://github.com/golang-jwt/jwt/pull/28)).
|
||||
* Fixed a potential issue that could occur when the verification of `exp`, `iat` or `nbf` was not required and contained invalid contents, i.e. non-numeric/date. Thanks for @thaJeztah for making us aware of that and @giorgos-f3 for originally reporting it to the formtech fork ([#40](https://github.com/golang-jwt/jwt/pull/40)).
|
||||
* Added support for EdDSA / ED25519 ([#36](https://github.com/golang-jwt/jwt/pull/36)).
|
||||
* Optimized allocations ([#33](https://github.com/golang-jwt/jwt/pull/33)).
|
||||
|
||||
#### 3.2.1
|
||||
|
||||
* **Import Path Change**: See MIGRATION_GUIDE.md for tips on updating your code
|
||||
* Changed the import path from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt`
|
||||
* Fixed type confusing issue between `string` and `[]string` in `VerifyAudience` ([#12](https://github.com/golang-jwt/jwt/pull/12)). This fixes CVE-2020-26160
|
||||
|
||||
#### 3.2.0
|
||||
|
||||
* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation
|
||||
@@ -115,4 +128,4 @@ It is likely the only integration change required here will be to change `func(t
|
||||
* First versioned release
|
||||
* API stabilized
|
||||
* Supports creating, signing, parsing, and validating JWT tokens
|
||||
* Supports RS256 and HS256 signing methods
|
||||
* Supports RS256 and HS256 signing methods
|
||||
Generated
Vendored
+22
-10
@@ -35,18 +35,18 @@ func (c StandardClaims) Valid() error {
|
||||
|
||||
// The claims below are optional, by default, so if they are set to the
|
||||
// default value in Go, let's not fail the verification for them.
|
||||
if c.VerifyExpiresAt(now, false) == false {
|
||||
if !c.VerifyExpiresAt(now, false) {
|
||||
delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
|
||||
vErr.Inner = fmt.Errorf("token is expired by %v", delta)
|
||||
vErr.Errors |= ValidationErrorExpired
|
||||
}
|
||||
|
||||
if c.VerifyIssuedAt(now, false) == false {
|
||||
if !c.VerifyIssuedAt(now, false) {
|
||||
vErr.Inner = fmt.Errorf("Token used before issued")
|
||||
vErr.Errors |= ValidationErrorIssuedAt
|
||||
}
|
||||
|
||||
if c.VerifyNotBefore(now, false) == false {
|
||||
if !c.VerifyNotBefore(now, false) {
|
||||
vErr.Inner = fmt.Errorf("token is not valid yet")
|
||||
vErr.Errors |= ValidationErrorNotValidYet
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func (c StandardClaims) Valid() error {
|
||||
// Compares the aud claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
|
||||
return verifyAud(c.Audience, cmp, req)
|
||||
return verifyAud([]string{c.Audience}, cmp, req)
|
||||
}
|
||||
|
||||
// Compares the exp claim against cmp.
|
||||
@@ -90,15 +90,27 @@ func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||
|
||||
// ----- helpers
|
||||
|
||||
func verifyAud(aud string, cmp string, required bool) bool {
|
||||
if aud == "" {
|
||||
func verifyAud(aud []string, cmp string, required bool) bool {
|
||||
if len(aud) == 0 {
|
||||
return !required
|
||||
}
|
||||
if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
// use a var here to keep constant time compare when looping over a number of claims
|
||||
result := false
|
||||
|
||||
var stringClaims string
|
||||
for _, a := range aud {
|
||||
if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 {
|
||||
result = true
|
||||
}
|
||||
stringClaims = stringClaims + a
|
||||
}
|
||||
|
||||
// case where "" is sent in one or many aud claims
|
||||
if len(stringClaims) == 0 {
|
||||
return !required
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func verifyExp(exp int64, now int64, required bool) bool {
|
||||
Generated
Vendored
Generated
Vendored
+9
-15
@@ -88,11 +88,11 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa
|
||||
hasher.Write([]byte(signingString))
|
||||
|
||||
// Verify the signature
|
||||
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true {
|
||||
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus {
|
||||
return nil
|
||||
} else {
|
||||
return ErrECDSAVerification
|
||||
}
|
||||
|
||||
return ErrECDSAVerification
|
||||
}
|
||||
|
||||
// Implements the Sign method from SigningMethod
|
||||
@@ -128,18 +128,12 @@ func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string
|
||||
keyBytes += 1
|
||||
}
|
||||
|
||||
// We serialize the outpus (r and s) into big-endian byte arrays and pad
|
||||
// them with zeros on the left to make sure the sizes work out. Both arrays
|
||||
// must be keyBytes long, and the output must be 2*keyBytes long.
|
||||
rBytes := r.Bytes()
|
||||
rBytesPadded := make([]byte, keyBytes)
|
||||
copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
|
||||
|
||||
sBytes := s.Bytes()
|
||||
sBytesPadded := make([]byte, keyBytes)
|
||||
copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
|
||||
|
||||
out := append(rBytesPadded, sBytesPadded...)
|
||||
// We serialize the outputs (r and s) into big-endian byte arrays
|
||||
// padded with zeros on the left to make sure the sizes work out.
|
||||
// Output must be 2*keyBytes long.
|
||||
out := make([]byte, 2*keyBytes)
|
||||
r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output.
|
||||
s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output.
|
||||
|
||||
return EncodeSegment(out), nil
|
||||
} else {
|
||||
Generated
Vendored
+3
-1
@@ -25,7 +25,9 @@ func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
|
||||
// Parse the key
|
||||
var parsedKey interface{}
|
||||
if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil {
|
||||
return nil, err
|
||||
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var pkey *ecdsa.PrivateKey
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"crypto/ed25519"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrEd25519Verification = errors.New("ed25519: verification error")
|
||||
)
|
||||
|
||||
// Implements the EdDSA family
|
||||
// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification
|
||||
type SigningMethodEd25519 struct{}
|
||||
|
||||
// Specific instance for EdDSA
|
||||
var (
|
||||
SigningMethodEdDSA *SigningMethodEd25519
|
||||
)
|
||||
|
||||
func init() {
|
||||
SigningMethodEdDSA = &SigningMethodEd25519{}
|
||||
RegisterSigningMethod(SigningMethodEdDSA.Alg(), func() SigningMethod {
|
||||
return SigningMethodEdDSA
|
||||
})
|
||||
}
|
||||
|
||||
func (m *SigningMethodEd25519) Alg() string {
|
||||
return "EdDSA"
|
||||
}
|
||||
|
||||
// Implements the Verify method from SigningMethod
|
||||
// For this verify method, key must be an ed25519.PublicKey
|
||||
func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error {
|
||||
var err error
|
||||
var ed25519Key ed25519.PublicKey
|
||||
var ok bool
|
||||
|
||||
if ed25519Key, ok = key.(ed25519.PublicKey); !ok {
|
||||
return ErrInvalidKeyType
|
||||
}
|
||||
|
||||
if len(ed25519Key) != ed25519.PublicKeySize {
|
||||
return ErrInvalidKey
|
||||
}
|
||||
|
||||
// Decode the signature
|
||||
var sig []byte
|
||||
if sig, err = DecodeSegment(signature); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify the signature
|
||||
if !ed25519.Verify(ed25519Key, []byte(signingString), sig) {
|
||||
return ErrEd25519Verification
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements the Sign method from SigningMethod
|
||||
// For this signing method, key must be an ed25519.PrivateKey
|
||||
func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) {
|
||||
var ed25519Key ed25519.PrivateKey
|
||||
var ok bool
|
||||
|
||||
if ed25519Key, ok = key.(ed25519.PrivateKey); !ok {
|
||||
return "", ErrInvalidKeyType
|
||||
}
|
||||
|
||||
// ed25519.Sign panics if private key not equal to ed25519.PrivateKeySize
|
||||
// this allows to avoid recover usage
|
||||
if len(ed25519Key) != ed25519.PrivateKeySize {
|
||||
return "", ErrInvalidKey
|
||||
}
|
||||
|
||||
// Sign the string and return the encoded result
|
||||
sig := ed25519.Sign(ed25519Key, []byte(signingString))
|
||||
return EncodeSegment(sig), nil
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ed25519"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotEdPrivateKey = errors.New("Key is not a valid Ed25519 private key")
|
||||
ErrNotEdPublicKey = errors.New("Key is not a valid Ed25519 public key")
|
||||
)
|
||||
|
||||
// Parse PEM-encoded Edwards curve private key
|
||||
func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) {
|
||||
var err error
|
||||
|
||||
// Parse PEM block
|
||||
var block *pem.Block
|
||||
if block, _ = pem.Decode(key); block == nil {
|
||||
return nil, ErrKeyMustBePEMEncoded
|
||||
}
|
||||
|
||||
// Parse the key
|
||||
var parsedKey interface{}
|
||||
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pkey ed25519.PrivateKey
|
||||
var ok bool
|
||||
if pkey, ok = parsedKey.(ed25519.PrivateKey); !ok {
|
||||
return nil, ErrNotEdPrivateKey
|
||||
}
|
||||
|
||||
return pkey, nil
|
||||
}
|
||||
|
||||
// Parse PEM-encoded Edwards curve public key
|
||||
func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) {
|
||||
var err error
|
||||
|
||||
// Parse PEM block
|
||||
var block *pem.Block
|
||||
if block, _ = pem.Decode(key); block == nil {
|
||||
return nil, ErrKeyMustBePEMEncoded
|
||||
}
|
||||
|
||||
// Parse the key
|
||||
var parsedKey interface{}
|
||||
if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pkey ed25519.PublicKey
|
||||
var ok bool
|
||||
if pkey, ok = parsedKey.(ed25519.PublicKey); !ok {
|
||||
return nil, ErrNotEdPublicKey
|
||||
}
|
||||
|
||||
return pkey, nil
|
||||
}
|
||||
Generated
Vendored
Generated
Vendored
Generated
Vendored
+43
-17
@@ -10,37 +10,59 @@ import (
|
||||
// This is the default claims type if you don't supply one
|
||||
type MapClaims map[string]interface{}
|
||||
|
||||
// Compares the aud claim against cmp.
|
||||
// VerifyAudience Compares the aud claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
|
||||
aud, _ := m["aud"].(string)
|
||||
var aud []string
|
||||
switch v := m["aud"].(type) {
|
||||
case string:
|
||||
aud = append(aud, v)
|
||||
case []string:
|
||||
aud = v
|
||||
case []interface{}:
|
||||
for _, a := range v {
|
||||
vs, ok := a.(string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
aud = append(aud, vs)
|
||||
}
|
||||
}
|
||||
return verifyAud(aud, cmp, req)
|
||||
}
|
||||
|
||||
// Compares the exp claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||
switch exp := m["exp"].(type) {
|
||||
exp, ok := m["exp"]
|
||||
if !ok {
|
||||
return !req
|
||||
}
|
||||
switch expType := exp.(type) {
|
||||
case float64:
|
||||
return verifyExp(int64(exp), cmp, req)
|
||||
return verifyExp(int64(expType), cmp, req)
|
||||
case json.Number:
|
||||
v, _ := exp.Int64()
|
||||
v, _ := expType.Int64()
|
||||
return verifyExp(v, cmp, req)
|
||||
}
|
||||
return req == false
|
||||
return false
|
||||
}
|
||||
|
||||
// Compares the iat claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
||||
switch iat := m["iat"].(type) {
|
||||
iat, ok := m["iat"]
|
||||
if !ok {
|
||||
return !req
|
||||
}
|
||||
switch iatType := iat.(type) {
|
||||
case float64:
|
||||
return verifyIat(int64(iat), cmp, req)
|
||||
return verifyIat(int64(iatType), cmp, req)
|
||||
case json.Number:
|
||||
v, _ := iat.Int64()
|
||||
v, _ := iatType.Int64()
|
||||
return verifyIat(v, cmp, req)
|
||||
}
|
||||
return req == false
|
||||
return false
|
||||
}
|
||||
|
||||
// Compares the iss claim against cmp.
|
||||
@@ -53,14 +75,18 @@ func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
|
||||
// Compares the nbf claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||
switch nbf := m["nbf"].(type) {
|
||||
nbf, ok := m["nbf"]
|
||||
if !ok {
|
||||
return !req
|
||||
}
|
||||
switch nbfType := nbf.(type) {
|
||||
case float64:
|
||||
return verifyNbf(int64(nbf), cmp, req)
|
||||
return verifyNbf(int64(nbfType), cmp, req)
|
||||
case json.Number:
|
||||
v, _ := nbf.Int64()
|
||||
v, _ := nbfType.Int64()
|
||||
return verifyNbf(v, cmp, req)
|
||||
}
|
||||
return req == false
|
||||
return false
|
||||
}
|
||||
|
||||
// Validates time based claims "exp, iat, nbf".
|
||||
@@ -71,17 +97,17 @@ func (m MapClaims) Valid() error {
|
||||
vErr := new(ValidationError)
|
||||
now := TimeFunc().Unix()
|
||||
|
||||
if m.VerifyExpiresAt(now, false) == false {
|
||||
if !m.VerifyExpiresAt(now, false) {
|
||||
vErr.Inner = errors.New("Token is expired")
|
||||
vErr.Errors |= ValidationErrorExpired
|
||||
}
|
||||
|
||||
if m.VerifyIssuedAt(now, false) == false {
|
||||
if !m.VerifyIssuedAt(now, false) {
|
||||
vErr.Inner = errors.New("Token used before issued")
|
||||
vErr.Errors |= ValidationErrorIssuedAt
|
||||
}
|
||||
|
||||
if m.VerifyNotBefore(now, false) == false {
|
||||
if !m.VerifyNotBefore(now, false) {
|
||||
vErr.Inner = errors.New("Token is not valid yet")
|
||||
vErr.Errors |= ValidationErrorNotValidYet
|
||||
}
|
||||
Generated
Vendored
Generated
Vendored
Generated
Vendored
Generated
Vendored
+27
-11
@@ -12,9 +12,14 @@ import (
|
||||
type SigningMethodRSAPSS struct {
|
||||
*SigningMethodRSA
|
||||
Options *rsa.PSSOptions
|
||||
// VerifyOptions is optional. If set overrides Options for rsa.VerifyPPS.
|
||||
// Used to accept tokens signed with rsa.PSSSaltLengthAuto, what doesn't follow
|
||||
// https://tools.ietf.org/html/rfc7518#section-3.5 but was used previously.
|
||||
// See https://github.com/dgrijalva/jwt-go/issues/285#issuecomment-437451244 for details.
|
||||
VerifyOptions *rsa.PSSOptions
|
||||
}
|
||||
|
||||
// Specific instances for RS/PS and company
|
||||
// Specific instances for RS/PS and company.
|
||||
var (
|
||||
SigningMethodPS256 *SigningMethodRSAPSS
|
||||
SigningMethodPS384 *SigningMethodRSAPSS
|
||||
@@ -24,13 +29,15 @@ var (
|
||||
func init() {
|
||||
// PS256
|
||||
SigningMethodPS256 = &SigningMethodRSAPSS{
|
||||
&SigningMethodRSA{
|
||||
SigningMethodRSA: &SigningMethodRSA{
|
||||
Name: "PS256",
|
||||
Hash: crypto.SHA256,
|
||||
},
|
||||
&rsa.PSSOptions{
|
||||
Options: &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||
},
|
||||
VerifyOptions: &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthAuto,
|
||||
Hash: crypto.SHA256,
|
||||
},
|
||||
}
|
||||
RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod {
|
||||
@@ -39,13 +46,15 @@ func init() {
|
||||
|
||||
// PS384
|
||||
SigningMethodPS384 = &SigningMethodRSAPSS{
|
||||
&SigningMethodRSA{
|
||||
SigningMethodRSA: &SigningMethodRSA{
|
||||
Name: "PS384",
|
||||
Hash: crypto.SHA384,
|
||||
},
|
||||
&rsa.PSSOptions{
|
||||
Options: &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||
},
|
||||
VerifyOptions: &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthAuto,
|
||||
Hash: crypto.SHA384,
|
||||
},
|
||||
}
|
||||
RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod {
|
||||
@@ -54,13 +63,15 @@ func init() {
|
||||
|
||||
// PS512
|
||||
SigningMethodPS512 = &SigningMethodRSAPSS{
|
||||
&SigningMethodRSA{
|
||||
SigningMethodRSA: &SigningMethodRSA{
|
||||
Name: "PS512",
|
||||
Hash: crypto.SHA512,
|
||||
},
|
||||
&rsa.PSSOptions{
|
||||
Options: &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||
},
|
||||
VerifyOptions: &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthAuto,
|
||||
Hash: crypto.SHA512,
|
||||
},
|
||||
}
|
||||
RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod {
|
||||
@@ -94,7 +105,12 @@ func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interf
|
||||
hasher := m.Hash.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
|
||||
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options)
|
||||
opts := m.Options
|
||||
if m.VerifyOptions != nil {
|
||||
opts = m.VerifyOptions
|
||||
}
|
||||
|
||||
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts)
|
||||
}
|
||||
|
||||
// Implements the Sign method from SigningMethod
|
||||
Generated
Vendored
+1
-1
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key")
|
||||
ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be a PEM encoded PKCS1 or PKCS8 key")
|
||||
ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key")
|
||||
ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key")
|
||||
)
|
||||
Generated
Vendored
Generated
Vendored
+3
-7
@@ -65,7 +65,7 @@ func (t *Token) SignedString(key interface{}) (string, error) {
|
||||
func (t *Token) SigningString() (string, error) {
|
||||
var err error
|
||||
parts := make([]string, 2)
|
||||
for i, _ := range parts {
|
||||
for i := range parts {
|
||||
var jsonValue []byte
|
||||
if i == 0 {
|
||||
if jsonValue, err = json.Marshal(t.Header); err != nil {
|
||||
@@ -95,14 +95,10 @@ func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token
|
||||
|
||||
// Encode JWT specific base64url encoding with padding stripped
|
||||
func EncodeSegment(seg []byte) string {
|
||||
return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
|
||||
return base64.RawURLEncoding.EncodeToString(seg)
|
||||
}
|
||||
|
||||
// Decode JWT specific base64url encoding with padding stripped
|
||||
func DecodeSegment(seg string) ([]byte, error) {
|
||||
if l := len(seg) % 4; l > 0 {
|
||||
seg += strings.Repeat("=", 4-l)
|
||||
}
|
||||
|
||||
return base64.URLEncoding.DecodeString(seg)
|
||||
return base64.RawURLEncoding.DecodeString(seg)
|
||||
}
|
||||
+1
-2
@@ -5,7 +5,7 @@ go 1.15
|
||||
require (
|
||||
cloud.google.com/go v0.67.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible
|
||||
github.com/gorilla/mux v1.6.2
|
||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1
|
||||
github.com/gorilla/sessions v1.1.1
|
||||
@@ -14,7 +14,6 @@ require (
|
||||
github.com/markbates/going v1.0.0
|
||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.4.0
|
||||
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
||||
|
||||
+4
-19
@@ -1,6 +1,4 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.30.0 h1:xKvyLgk56d0nksWq49J0UyGEeUIicTl4+UBiX1NPX9g=
|
||||
cloud.google.com/go v0.30.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
@@ -14,8 +12,8 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.63.0/go.mod h1:GmezbQc7T2snqkEXWfZ0sy0VfkB/ivI2DdtJL2DEmlg=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.67.0 h1:YIkzmqUfVGiGPpT98L8sVvUIkDno6UlrDxw4NR6z5ak=
|
||||
cloud.google.com/go v0.67.0/go.mod h1:YNan/mUhNZFrYUor0vqrsQ0Ffl7Xtm/ACOy/vsTS858=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
@@ -43,12 +41,9 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/damonkeys/goth v1.64.2 h1:I2cB72NAa1tJBI1TcLYn7H6hBeHpwm5y8Ew+VeSZXPg=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -56,6 +51,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -67,7 +64,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -133,8 +129,6 @@ github.com/lestrrat-go/jwx v0.9.0 h1:Fnd0EWzTm0kFrBPzE/PEPp9nzllES5buMkksPMjEKpM
|
||||
github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk=
|
||||
github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0=
|
||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
|
||||
github.com/markbates/goth v1.65.0 h1:IbXpMneUhqbxgJ8JP1Ghl8ghlAaVX66jWDAapU1KxqU=
|
||||
github.com/markbates/goth v1.65.0/go.mod h1:65frybxoeSCfORin51KOKqAKbIh7wREIDvdCkdWj//4=
|
||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA=
|
||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -143,10 +137,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -192,7 +184,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225 h1:kNX+jCowfMYzvlSvJu5pQWEmyWFrBXJ3PBy10xKMXK8=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -218,13 +209,10 @@ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 h1:YfxMZzv3PjGonQYNUaeU2+DhAdqOxerQ30JFB6WgAXo=
|
||||
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd h1:QQhib242ErYDSMitlBm8V7wYCm/1a25hV8qMadIKLPA=
|
||||
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -232,7 +220,6 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -314,7 +301,6 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200806022845-90696ccdc692/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
@@ -375,7 +361,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200929141702-51c3e5b607fe/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user