mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-18 00:01:32 -04:00
Compare commits
20 Commits
2b3f12f6fd
...
4fcf3a3f90
Author | SHA1 | Date | |
---|---|---|---|
|
4fcf3a3f90 | ||
|
34ae184622 | ||
|
1b950b98cf | ||
|
35d2fa744a | ||
|
97aacc3ea1 | ||
|
a82b9016c3 | ||
|
d845be661f | ||
|
d2128b44f7 | ||
|
330b166423 | ||
|
f4ce8c73fb | ||
|
cfc7a4efdb | ||
|
9aaf6998b7 | ||
|
018815215f | ||
|
36d1d5fb78 | ||
|
c3d9a70d0a | ||
|
9a83aa28a3 | ||
|
3596df52c0 | ||
|
1d64eafe8f | ||
|
b811ab48e5 | ||
|
ef11d41639 |
25
.drone.yml
25
.drone.yml
@ -12,6 +12,9 @@ trigger:
|
||||
- push
|
||||
- tag
|
||||
- pull_request
|
||||
paths:
|
||||
exclude:
|
||||
- docs/**
|
||||
|
||||
volumes:
|
||||
- name: deps
|
||||
@ -112,7 +115,6 @@ steps:
|
||||
image: golang:1.19 # this step is kept as the lowest version of golang that we support
|
||||
pull: always
|
||||
environment:
|
||||
GO111MODULE: on
|
||||
GOPROXY: https://goproxy.io
|
||||
commands:
|
||||
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
||||
@ -124,7 +126,6 @@ steps:
|
||||
- name: build-backend-arm64
|
||||
image: golang:1.20
|
||||
environment:
|
||||
GO111MODULE: on
|
||||
GOPROXY: https://goproxy.io
|
||||
GOOS: linux
|
||||
GOARCH: arm64
|
||||
@ -140,7 +141,6 @@ steps:
|
||||
- name: build-backend-windows
|
||||
image: golang:1.20
|
||||
environment:
|
||||
GO111MODULE: on
|
||||
GOPROXY: https://goproxy.io
|
||||
GOOS: windows
|
||||
GOARCH: amd64
|
||||
@ -155,7 +155,6 @@ steps:
|
||||
- name: build-backend-386
|
||||
image: golang:1.20
|
||||
environment:
|
||||
GO111MODULE: on
|
||||
GOPROXY: https://goproxy.io
|
||||
GOOS: linux
|
||||
GOARCH: 386
|
||||
@ -183,6 +182,9 @@ trigger:
|
||||
- push
|
||||
- tag
|
||||
- pull_request
|
||||
paths:
|
||||
exclude:
|
||||
- docs/**
|
||||
|
||||
volumes:
|
||||
- name: deps
|
||||
@ -410,6 +412,9 @@ trigger:
|
||||
- push
|
||||
- tag
|
||||
- pull_request
|
||||
paths:
|
||||
exclude:
|
||||
- docs/**
|
||||
|
||||
volumes:
|
||||
- name: deps
|
||||
@ -517,6 +522,9 @@ depends_on:
|
||||
trigger:
|
||||
event:
|
||||
- pull_request
|
||||
paths:
|
||||
exclude:
|
||||
- docs/**
|
||||
|
||||
volumes:
|
||||
- name: deps
|
||||
@ -696,6 +704,9 @@ trigger:
|
||||
- "release/*"
|
||||
event:
|
||||
- push
|
||||
paths:
|
||||
exclude:
|
||||
- docs/**
|
||||
|
||||
depends_on:
|
||||
- testing-amd64
|
||||
@ -947,6 +958,9 @@ trigger:
|
||||
- push
|
||||
- tag
|
||||
- pull_request
|
||||
paths:
|
||||
include:
|
||||
- docs/**
|
||||
|
||||
steps:
|
||||
- name: build-docs
|
||||
@ -1241,6 +1255,9 @@ depends_on:
|
||||
trigger:
|
||||
ref:
|
||||
- "refs/pull/**"
|
||||
paths:
|
||||
exclude:
|
||||
- docs/**
|
||||
|
||||
steps:
|
||||
- name: dryrun
|
||||
|
16
.github/pull_request_template.md
vendored
16
.github/pull_request_template.md
vendored
@ -1,9 +1,9 @@
|
||||
<!--
|
||||
|
||||
<!-- start tips -->
|
||||
Please check the following:
|
||||
|
||||
1. Make sure you are targeting the `main` branch, pull requests on release branches are only allowed for bug fixes.
|
||||
2. Read contributing guidelines: https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md
|
||||
3. Describe what your pull request does and which issue you're targeting (if any)
|
||||
|
||||
-->
|
||||
1. Make sure you are targeting the `main` branch, pull requests on release branches are only allowed for backports.
|
||||
2. Make sure you have read contributing guidelines: https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md .
|
||||
3. Describe what your pull request does and which issue you're targeting (if any).
|
||||
4. It is recommended to enable "Allow edits by maintainers", so maintainers can help more easily.
|
||||
5. Your input here will be included in the commit message when this PR has been merged. If you don't want some content to be included, please separate them with a line like `---`.
|
||||
6. Delete all these tips before posting.
|
||||
<!-- end tips -->
|
||||
|
37
CHANGELOG.md
37
CHANGELOG.md
@ -4,6 +4,43 @@ 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.18.4](https://github.com/go-gitea/gitea/releases/tag/1.18.4) - 2023-02-20
|
||||
|
||||
* SECURITY
|
||||
* Provide the ability to set password hash algorithm parameters (#22942) (#22943)
|
||||
* Add command to bulk set must-change-password (#22823) (#22928)
|
||||
* ENHANCEMENTS
|
||||
* Use import of OCI structs (#22765) (#22805)
|
||||
* Fix color of tertiary button on dark theme (#22739) (#22744)
|
||||
* Link issue and pull requests status change in UI notifications directly to their event in the timelined view. (#22627) (#22642)
|
||||
* BUGFIXES
|
||||
* Notify on container image create (#22806) (#22965)
|
||||
* Fix blame view missing lines (#22826) (#22929)
|
||||
* Fix incorrect role labels for migrated issues and comments (#22914) (#22923)
|
||||
* Fix PR file tree folders no longer collapsing (#22864) (#22872)
|
||||
* Escape filename when assemble URL (#22850) (#22871)
|
||||
* Fix isAllowed of escapeStreamer (#22814) (#22837)
|
||||
* Load issue before accessing index in merge message (#22822) (#22830)
|
||||
* Improve trace logging for pulls and processes (#22633) (#22812)
|
||||
* Fix restore repo bug, clarify the problem of ForeignIndex (#22776) (#22794)
|
||||
* Add default user visibility to cli command "admin user create" (#22750) (#22760)
|
||||
* Escape path for the file list (#22741) (#22757)
|
||||
* Fix bugs with WebAuthn preventing sign in and registration. (#22651) (#22721)
|
||||
* Add missing close bracket in imagediff (#22710) (#22712)
|
||||
* Move code comments to a standalone file and fix the bug when adding a reply to an outdated review appears to not post(#20821) (#22707)
|
||||
* Fix line spacing for plaintext previews (#22699) (#22701)
|
||||
* Fix wrong hint when deleting a branch successfully from pull request UI (#22673) (#22698)
|
||||
* Fix README TOC links (#22577) (#22677)
|
||||
* Fix missing message in git hook when pull requests disabled on fork (#22625) (#22658)
|
||||
* Improve checkIfPRContentChanged (#22611) (#22644)
|
||||
* Prevent duplicate labels when importing more than 99 (#22591) (#22598)
|
||||
* Don't return duplicated users who can create org repo (#22560) (#22562)
|
||||
* BUILD
|
||||
* Upgrade golangcilint to v1.51.0 (#22764)
|
||||
* MISC
|
||||
* Use proxy for pull mirror (#22771) (#22772)
|
||||
* Use `--index-url` in PyPi description (#22620) (#22636)
|
||||
|
||||
## [1.18.3](https://github.com/go-gitea/gitea/releases/tag/v1.18.3) - 2023-01-23
|
||||
|
||||
* SECURITY
|
||||
|
@ -47,3 +47,5 @@ Wim <wim@42.be> (@42wim)
|
||||
Xinyu Zhou <i@sourcehut.net> (@xin-u)
|
||||
Jason Song <i@wolfogre.com> (@wolfogre)
|
||||
Yarden Shoham <hrsi88@gmail.com> (@yardenshoham)
|
||||
Yu Tian <zettat123@gmail.com> (@Zettat123)
|
||||
Eddie Yang <576951401@qq.com> (@yp05327)
|
||||
|
6
go.mod
6
go.mod
@ -103,10 +103,10 @@ require (
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20220924101305-151362477c87
|
||||
github.com/yuin/goldmark-meta v1.1.0
|
||||
golang.org/x/crypto v0.4.0
|
||||
golang.org/x/net v0.4.0
|
||||
golang.org/x/net v0.7.0
|
||||
golang.org/x/oauth2 v0.3.0
|
||||
golang.org/x/sys v0.3.0
|
||||
golang.org/x/text v0.5.0
|
||||
golang.org/x/sys v0.5.0
|
||||
golang.org/x/text v0.7.0
|
||||
golang.org/x/tools v0.1.12
|
||||
google.golang.org/grpc v1.47.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
|
13
go.sum
13
go.sum
@ -1463,8 +1463,8 @@ golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
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=
|
||||
@ -1609,14 +1609,15 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1627,8 +1628,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -168,10 +168,23 @@ var allAccessTokenScopeBits = map[AccessTokenScope]AccessTokenScopeBitmap{
|
||||
|
||||
// Parse parses the scope string into a bitmap, thus removing possible duplicates.
|
||||
func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) {
|
||||
list := strings.Split(string(s), ",")
|
||||
|
||||
var bitmap AccessTokenScopeBitmap
|
||||
for _, v := range list {
|
||||
|
||||
// The following is the more performant equivalent of 'for _, v := range strings.Split(remainingScope, ",")' as this is hot code
|
||||
remainingScopes := string(s)
|
||||
for len(remainingScopes) > 0 {
|
||||
i := strings.IndexByte(remainingScopes, ',')
|
||||
var v string
|
||||
if i < 0 {
|
||||
v = remainingScopes
|
||||
remainingScopes = ""
|
||||
} else if i+1 >= len(remainingScopes) {
|
||||
v = remainingScopes[:i]
|
||||
remainingScopes = ""
|
||||
} else {
|
||||
v = remainingScopes[:i]
|
||||
remainingScopes = remainingScopes[i+1:]
|
||||
}
|
||||
singleScope := AccessTokenScope(v)
|
||||
if singleScope == "" {
|
||||
continue
|
||||
@ -187,9 +200,15 @@ func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) {
|
||||
}
|
||||
bitmap |= bits
|
||||
}
|
||||
|
||||
return bitmap, nil
|
||||
}
|
||||
|
||||
// StringSlice returns the AccessTokenScope as a []string
|
||||
func (s AccessTokenScope) StringSlice() []string {
|
||||
return strings.Split(string(s), ",")
|
||||
}
|
||||
|
||||
// Normalize returns a normalized scope string without any duplicates.
|
||||
func (s AccessTokenScope) Normalize() (AccessTokenScope, error) {
|
||||
bitmap, err := s.Parse()
|
||||
|
@ -8,8 +8,8 @@
|
||||
email: user1@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user1
|
||||
@ -45,8 +45,8 @@
|
||||
email: user2@example.com
|
||||
keep_email_private: true
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user2
|
||||
@ -82,8 +82,8 @@
|
||||
email: user3@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: onmention
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user3
|
||||
@ -119,8 +119,8 @@
|
||||
email: user4@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: onmention
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user4
|
||||
@ -156,8 +156,8 @@
|
||||
email: user5@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user5
|
||||
@ -193,8 +193,8 @@
|
||||
email: user6@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user6
|
||||
@ -230,8 +230,8 @@
|
||||
email: user7@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: disabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user7
|
||||
@ -267,8 +267,8 @@
|
||||
email: user8@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user8
|
||||
@ -304,8 +304,8 @@
|
||||
email: user9@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: onmention
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user9
|
||||
@ -341,8 +341,8 @@
|
||||
email: user10@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user10
|
||||
@ -378,8 +378,8 @@
|
||||
email: user11@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user11
|
||||
@ -415,8 +415,8 @@
|
||||
email: user12@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user12
|
||||
@ -452,8 +452,8 @@
|
||||
email: user13@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user13
|
||||
@ -489,8 +489,8 @@
|
||||
email: user14@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user14
|
||||
@ -526,8 +526,8 @@
|
||||
email: user15@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user15
|
||||
@ -563,8 +563,8 @@
|
||||
email: user16@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user16
|
||||
@ -600,8 +600,8 @@
|
||||
email: user17@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user17
|
||||
@ -637,8 +637,8 @@
|
||||
email: user18@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user18
|
||||
@ -674,8 +674,8 @@
|
||||
email: user19@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user19
|
||||
@ -711,8 +711,8 @@
|
||||
email: user20@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user20
|
||||
@ -748,8 +748,8 @@
|
||||
email: user21@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user21
|
||||
@ -785,8 +785,8 @@
|
||||
email: limited_org@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: limited_org
|
||||
@ -822,8 +822,8 @@
|
||||
email: privated_org@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: privated_org
|
||||
@ -859,8 +859,8 @@
|
||||
email: user24@example.com
|
||||
keep_email_private: true
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user24
|
||||
@ -896,8 +896,8 @@
|
||||
email: org25@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: org25
|
||||
@ -933,8 +933,8 @@
|
||||
email: org26@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: onmention
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: org26
|
||||
@ -970,8 +970,8 @@
|
||||
email: user27@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user27
|
||||
@ -1007,8 +1007,8 @@
|
||||
email: user28@example.com
|
||||
keep_email_private: true
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user28
|
||||
@ -1044,8 +1044,8 @@
|
||||
email: user29@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user29
|
||||
@ -1081,8 +1081,8 @@
|
||||
email: user30@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user30
|
||||
@ -1118,8 +1118,8 @@
|
||||
email: user31@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user31
|
||||
@ -1155,8 +1155,8 @@
|
||||
email: user32@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f47017
|
||||
passwd_hash_algo: argon2
|
||||
passwd: ZogKvWdyEx:notpassword
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user32
|
||||
@ -1192,8 +1192,8 @@
|
||||
email: user33@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: e82bc8ae42a53b98c3bd0f941aacc4aa2a264407534b0a11bf270137f67af912f694b67951f92148c45f91717e1478ca7889
|
||||
passwd_hash_algo: pbkdf2$50000$50
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: user33
|
||||
|
@ -251,13 +251,15 @@ func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
|
||||
|
||||
// LoadPullRequest loads pull request info
|
||||
func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) {
|
||||
if issue.IsPull && issue.PullRequest == nil {
|
||||
issue.PullRequest, err = GetPullRequestByIssueID(ctx, issue.ID)
|
||||
if err != nil {
|
||||
if IsErrPullRequestNotExist(err) {
|
||||
return err
|
||||
if issue.IsPull {
|
||||
if issue.PullRequest == nil {
|
||||
issue.PullRequest, err = GetPullRequestByIssueID(ctx, issue.ID)
|
||||
if err != nil {
|
||||
if IsErrPullRequestNotExist(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("getPullRequestByIssueID [%d]: %w", issue.ID, err)
|
||||
}
|
||||
return fmt.Errorf("getPullRequestByIssueID [%d]: %w", issue.ID, err)
|
||||
}
|
||||
issue.PullRequest.Issue = issue
|
||||
}
|
||||
@ -347,7 +349,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = issue.loadProject(ctx); err != nil {
|
||||
if err = issue.LoadProject(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// LoadProject load the project the issue was assigned to
|
||||
func (issue *Issue) LoadProject() (err error) {
|
||||
return issue.loadProject(db.DefaultContext)
|
||||
}
|
||||
|
||||
func (issue *Issue) loadProject(ctx context.Context) (err error) {
|
||||
func (issue *Issue) LoadProject(ctx context.Context) (err error) {
|
||||
if issue.Project == nil {
|
||||
var p project_model.Project
|
||||
if _, err = db.GetEngine(ctx).Table("project").
|
||||
|
@ -9,6 +9,8 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/auth/password/hash"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-testfixtures/testfixtures/v3"
|
||||
"xorm.io/xorm"
|
||||
@ -64,6 +66,11 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// register the dummy hash algorithm function used in the test fixtures
|
||||
_ = hash.Register("dummy", hash.NewDummyHasher)
|
||||
|
||||
setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -115,5 +122,8 @@ func LoadFixtures(engine ...*xorm.Engine) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = hash.Register("dummy", hash.NewDummyHasher)
|
||||
setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
Register("argon2", NewArgon2Hasher)
|
||||
MustRegister("argon2", NewArgon2Hasher)
|
||||
}
|
||||
|
||||
// Argon2Hasher implements PasswordHasher
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
Register("bcrypt", NewBcryptHasher)
|
||||
MustRegister("bcrypt", NewBcryptHasher)
|
||||
}
|
||||
|
||||
// BcryptHasher implements PasswordHasher
|
||||
|
33
modules/auth/password/hash/dummy.go
Normal file
33
modules/auth/password/hash/dummy.go
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package hash
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// DummyHasher implements PasswordHasher and is a dummy hasher that simply
|
||||
// puts the password in place with its salt
|
||||
// This SHOULD NOT be used in production and is provided to make the integration
|
||||
// tests faster only
|
||||
type DummyHasher struct{}
|
||||
|
||||
// HashWithSaltBytes a provided password and salt
|
||||
func (hasher *DummyHasher) HashWithSaltBytes(password string, salt []byte) string {
|
||||
if hasher == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(salt) == 10 {
|
||||
return string(salt) + ":" + password
|
||||
}
|
||||
|
||||
return hex.EncodeToString(salt) + ":" + password
|
||||
}
|
||||
|
||||
// NewDummyHasher is a factory method to create a DummyHasher
|
||||
// Any provided configuration is ignored
|
||||
func NewDummyHasher(_ string) *DummyHasher {
|
||||
return &DummyHasher{}
|
||||
}
|
25
modules/auth/password/hash/dummy_test.go
Normal file
25
modules/auth/password/hash/dummy_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package hash
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDummyHasher(t *testing.T) {
|
||||
dummy := &PasswordHashAlgorithm{
|
||||
PasswordSaltHasher: NewDummyHasher(""),
|
||||
Specification: "dummy",
|
||||
}
|
||||
|
||||
password, salt := "password", "ZogKvWdyEx"
|
||||
|
||||
hash, err := dummy.Hash(password, salt)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, hash, salt+":"+password)
|
||||
|
||||
assert.True(t, dummy.VerifyPassword(password, hash, salt))
|
||||
}
|
@ -83,17 +83,26 @@ var (
|
||||
availableHasherFactories = map[string]func(string) PasswordSaltHasher{}
|
||||
)
|
||||
|
||||
// MustRegister registers a PasswordSaltHasher with the availableHasherFactories
|
||||
// Caution: This is not thread safe.
|
||||
func MustRegister[T PasswordSaltHasher](name string, newFn func(config string) T) {
|
||||
if err := Register(name, newFn); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Register registers a PasswordSaltHasher with the availableHasherFactories
|
||||
// Caution: This is not thread safe.
|
||||
func Register[T PasswordSaltHasher](name string, newFn func(config string) T) {
|
||||
func Register[T PasswordSaltHasher](name string, newFn func(config string) T) error {
|
||||
if _, has := availableHasherFactories[name]; has {
|
||||
panic(fmt.Errorf("duplicate registration of password salt hasher: %s", name))
|
||||
return fmt.Errorf("duplicate registration of password salt hasher: %s", name)
|
||||
}
|
||||
|
||||
availableHasherFactories[name] = func(config string) PasswordSaltHasher {
|
||||
n := newFn(config)
|
||||
return n
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// In early versions of gitea the password hash algorithm field of a user could be
|
||||
|
@ -19,16 +19,20 @@ func (t testSaltHasher) HashWithSaltBytes(password string, salt []byte) string {
|
||||
}
|
||||
|
||||
func Test_registerHasher(t *testing.T) {
|
||||
Register("Test_registerHasher", func(config string) testSaltHasher {
|
||||
MustRegister("Test_registerHasher", func(config string) testSaltHasher {
|
||||
return testSaltHasher(config)
|
||||
})
|
||||
|
||||
assert.Panics(t, func() {
|
||||
Register("Test_registerHasher", func(config string) testSaltHasher {
|
||||
MustRegister("Test_registerHasher", func(config string) testSaltHasher {
|
||||
return testSaltHasher(config)
|
||||
})
|
||||
})
|
||||
|
||||
assert.Error(t, Register("Test_registerHasher", func(config string) testSaltHasher {
|
||||
return testSaltHasher(config)
|
||||
}))
|
||||
|
||||
assert.Equal(t, "password$salt$",
|
||||
Parse("Test_registerHasher").PasswordSaltHasher.HashWithSaltBytes("password", []byte("salt")))
|
||||
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
Register("pbkdf2", NewPBKDF2Hasher)
|
||||
MustRegister("pbkdf2", NewPBKDF2Hasher)
|
||||
}
|
||||
|
||||
// PBKDF2Hasher implements PasswordHasher
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
Register("scrypt", NewScryptHasher)
|
||||
MustRegister("scrypt", NewScryptHasher)
|
||||
}
|
||||
|
||||
// ScryptHasher implements PasswordHasher
|
||||
|
@ -6,8 +6,8 @@ package context
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
@ -25,9 +25,9 @@ func mustMapSetting(rootCfg ConfigProvider, sectionName string, setting interfac
|
||||
}
|
||||
}
|
||||
|
||||
func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey string) {
|
||||
func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) {
|
||||
if rootCfg.Section(oldSection).HasKey(oldKey) {
|
||||
log.Error("Deprecated fallback `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be removed in v1.19.0", oldSection, oldKey, newSection, newKey)
|
||||
log.Error("Deprecated fallback `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,12 +56,13 @@ func loadIndexerFrom(rootCfg ConfigProvider) {
|
||||
Indexer.IssueIndexerName = sec.Key("ISSUE_INDEXER_NAME").MustString(Indexer.IssueIndexerName)
|
||||
|
||||
// The following settings are deprecated and can be overridden by settings in [queue] or [queue.issue_indexer]
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_TYPE", "queue.issue_indexer", "TYPE")
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_DIR", "queue.issue_indexer", "DATADIR")
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_CONN_STR", "queue.issue_indexer", "CONN_STR")
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_BATCH_NUMBER", "queue.issue_indexer", "BATCH_LENGTH")
|
||||
deprecatedSetting(rootCfg, "indexer", "UPDATE_BUFFER_LEN", "queue.issue_indexer", "LENGTH")
|
||||
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
|
||||
// if these are removed, the warning will not be shown
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_TYPE", "queue.issue_indexer", "TYPE", "v1.19.0")
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_DIR", "queue.issue_indexer", "DATADIR", "v1.19.0")
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_CONN_STR", "queue.issue_indexer", "CONN_STR", "v1.19.0")
|
||||
deprecatedSetting(rootCfg, "indexer", "ISSUE_INDEXER_QUEUE_BATCH_NUMBER", "queue.issue_indexer", "BATCH_LENGTH", "v1.19.0")
|
||||
deprecatedSetting(rootCfg, "indexer", "UPDATE_BUFFER_LEN", "queue.issue_indexer", "LENGTH", "v1.19.0")
|
||||
|
||||
Indexer.RepoIndexerEnabled = sec.Key("REPO_INDEXER_ENABLED").MustBool(false)
|
||||
Indexer.RepoType = sec.Key("REPO_INDEXER_TYPE").MustString("bleve")
|
||||
|
@ -35,8 +35,9 @@ func loadLFSFrom(rootCfg ConfigProvider) {
|
||||
storageType := lfsSec.Key("STORAGE_TYPE").MustString("")
|
||||
|
||||
// Specifically default PATH to LFS_CONTENT_PATH
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
deprecatedSetting(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH")
|
||||
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
|
||||
// if these are removed, the warning will not be shown
|
||||
deprecatedSetting(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH", "v1.19.0")
|
||||
lfsSec.Key("PATH").MustString(
|
||||
sec.Key("LFS_CONTENT_PATH").String())
|
||||
|
||||
|
@ -64,16 +64,16 @@ func loadMailerFrom(rootCfg ConfigProvider) {
|
||||
}
|
||||
|
||||
// Handle Deprecations and map on to new configuration
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "MAILER_TYPE", "mailer", "PROTOCOL")
|
||||
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
|
||||
// if these are removed, the warning will not be shown
|
||||
deprecatedSetting(rootCfg, "mailer", "MAILER_TYPE", "mailer", "PROTOCOL", "v1.19.0")
|
||||
if sec.HasKey("MAILER_TYPE") && !sec.HasKey("PROTOCOL") {
|
||||
if sec.Key("MAILER_TYPE").String() == "sendmail" {
|
||||
sec.Key("PROTOCOL").MustString("sendmail")
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "HOST", "mailer", "SMTP_ADDR")
|
||||
deprecatedSetting(rootCfg, "mailer", "HOST", "mailer", "SMTP_ADDR", "v1.19.0")
|
||||
if sec.HasKey("HOST") && !sec.HasKey("SMTP_ADDR") {
|
||||
givenHost := sec.Key("HOST").String()
|
||||
addr, port, err := net.SplitHostPort(givenHost)
|
||||
@ -89,8 +89,7 @@ func loadMailerFrom(rootCfg ConfigProvider) {
|
||||
sec.Key("SMTP_PORT").MustString(port)
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "IS_TLS_ENABLED", "mailer", "PROTOCOL")
|
||||
deprecatedSetting(rootCfg, "mailer", "IS_TLS_ENABLED", "mailer", "PROTOCOL", "v1.19.0")
|
||||
if sec.HasKey("IS_TLS_ENABLED") && !sec.HasKey("PROTOCOL") {
|
||||
if sec.Key("IS_TLS_ENABLED").MustBool() {
|
||||
sec.Key("PROTOCOL").MustString("smtps")
|
||||
@ -99,38 +98,32 @@ func loadMailerFrom(rootCfg ConfigProvider) {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "DISABLE_HELO", "mailer", "ENABLE_HELO")
|
||||
deprecatedSetting(rootCfg, "mailer", "DISABLE_HELO", "mailer", "ENABLE_HELO", "v1.19.0")
|
||||
if sec.HasKey("DISABLE_HELO") && !sec.HasKey("ENABLE_HELO") {
|
||||
sec.Key("ENABLE_HELO").MustBool(!sec.Key("DISABLE_HELO").MustBool())
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "SKIP_VERIFY", "mailer", "FORCE_TRUST_SERVER_CERT")
|
||||
deprecatedSetting(rootCfg, "mailer", "SKIP_VERIFY", "mailer", "FORCE_TRUST_SERVER_CERT", "v1.19.0")
|
||||
if sec.HasKey("SKIP_VERIFY") && !sec.HasKey("FORCE_TRUST_SERVER_CERT") {
|
||||
sec.Key("FORCE_TRUST_SERVER_CERT").MustBool(sec.Key("SKIP_VERIFY").MustBool())
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "USE_CERTIFICATE", "mailer", "USE_CLIENT_CERT")
|
||||
deprecatedSetting(rootCfg, "mailer", "USE_CERTIFICATE", "mailer", "USE_CLIENT_CERT", "v1.19.0")
|
||||
if sec.HasKey("USE_CERTIFICATE") && !sec.HasKey("USE_CLIENT_CERT") {
|
||||
sec.Key("USE_CLIENT_CERT").MustBool(sec.Key("USE_CERTIFICATE").MustBool())
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "CERT_FILE", "mailer", "CLIENT_CERT_FILE")
|
||||
deprecatedSetting(rootCfg, "mailer", "CERT_FILE", "mailer", "CLIENT_CERT_FILE", "v1.19.0")
|
||||
if sec.HasKey("CERT_FILE") && !sec.HasKey("CLIENT_CERT_FILE") {
|
||||
sec.Key("CERT_FILE").MustString(sec.Key("CERT_FILE").String())
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "KEY_FILE", "mailer", "CLIENT_KEY_FILE")
|
||||
deprecatedSetting(rootCfg, "mailer", "KEY_FILE", "mailer", "CLIENT_KEY_FILE", "v1.19.0")
|
||||
if sec.HasKey("KEY_FILE") && !sec.HasKey("CLIENT_KEY_FILE") {
|
||||
sec.Key("KEY_FILE").MustString(sec.Key("KEY_FILE").String())
|
||||
}
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.19.0
|
||||
deprecatedSetting(rootCfg, "mailer", "ENABLE_HTML_ALTERNATIVE", "mailer", "SEND_AS_PLAIN_TEXT")
|
||||
deprecatedSetting(rootCfg, "mailer", "ENABLE_HTML_ALTERNATIVE", "mailer", "SEND_AS_PLAIN_TEXT", "v1.19.0")
|
||||
if sec.HasKey("ENABLE_HTML_ALTERNATIVE") && !sec.HasKey("SEND_AS_PLAIN_TEXT") {
|
||||
sec.Key("SEND_AS_PLAIN_TEXT").MustBool(!sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(false))
|
||||
}
|
||||
|
@ -27,8 +27,9 @@ var Mirror = struct {
|
||||
func loadMirrorFrom(rootCfg ConfigProvider) {
|
||||
// Handle old configuration through `[repository]` `DISABLE_MIRRORS`
|
||||
// - please note this was badly named and only disabled the creation of new pull mirrors
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
deprecatedSetting(rootCfg, "repository", "DISABLE_MIRRORS", "mirror", "ENABLED")
|
||||
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
|
||||
// if these are removed, the warning will not be shown
|
||||
deprecatedSetting(rootCfg, "repository", "DISABLE_MIRRORS", "mirror", "ENABLED", "v1.19.0")
|
||||
if rootCfg.Section("repository").Key("DISABLE_MIRRORS").MustBool(false) {
|
||||
Mirror.DisableNewPull = true
|
||||
}
|
||||
|
@ -178,38 +178,40 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
||||
switch protocolCfg {
|
||||
case "https":
|
||||
Protocol = HTTPS
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
|
||||
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
|
||||
// if these are removed, the warning will not be shown
|
||||
if sec.HasKey("ENABLE_ACME") {
|
||||
EnableAcme = sec.Key("ENABLE_ACME").MustBool(false)
|
||||
} else {
|
||||
deprecatedSetting(rootCfg, "server", "ENABLE_LETSENCRYPT", "server", "ENABLE_ACME")
|
||||
deprecatedSetting(rootCfg, "server", "ENABLE_LETSENCRYPT", "server", "ENABLE_ACME", "v1.19.0")
|
||||
EnableAcme = sec.Key("ENABLE_LETSENCRYPT").MustBool(false)
|
||||
}
|
||||
if EnableAcme {
|
||||
AcmeURL = sec.Key("ACME_URL").MustString("")
|
||||
AcmeCARoot = sec.Key("ACME_CA_ROOT").MustString("")
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
|
||||
if sec.HasKey("ACME_ACCEPTTOS") {
|
||||
AcmeTOS = sec.Key("ACME_ACCEPTTOS").MustBool(false)
|
||||
} else {
|
||||
deprecatedSetting(rootCfg, "server", "LETSENCRYPT_ACCEPTTOS", "server", "ACME_ACCEPTTOS")
|
||||
deprecatedSetting(rootCfg, "server", "LETSENCRYPT_ACCEPTTOS", "server", "ACME_ACCEPTTOS", "v1.19.0")
|
||||
AcmeTOS = sec.Key("LETSENCRYPT_ACCEPTTOS").MustBool(false)
|
||||
}
|
||||
if !AcmeTOS {
|
||||
log.Fatal("ACME TOS is not accepted (ACME_ACCEPTTOS).")
|
||||
}
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
|
||||
if sec.HasKey("ACME_DIRECTORY") {
|
||||
AcmeLiveDirectory = sec.Key("ACME_DIRECTORY").MustString("https")
|
||||
} else {
|
||||
deprecatedSetting(rootCfg, "server", "LETSENCRYPT_DIRECTORY", "server", "ACME_DIRECTORY")
|
||||
deprecatedSetting(rootCfg, "server", "LETSENCRYPT_DIRECTORY", "server", "ACME_DIRECTORY", "v1.19.0")
|
||||
AcmeLiveDirectory = sec.Key("LETSENCRYPT_DIRECTORY").MustString("https")
|
||||
}
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
|
||||
if sec.HasKey("ACME_EMAIL") {
|
||||
AcmeEmail = sec.Key("ACME_EMAIL").MustString("")
|
||||
} else {
|
||||
deprecatedSetting(rootCfg, "server", "LETSENCRYPT_EMAIL", "server", "ACME_EMAIL")
|
||||
deprecatedSetting(rootCfg, "server", "LETSENCRYPT_EMAIL", "server", "ACME_EMAIL", "v1.19.0")
|
||||
AcmeEmail = sec.Key("LETSENCRYPT_EMAIL").MustString("")
|
||||
}
|
||||
} else {
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/auth/password/hash"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/user"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
@ -232,6 +233,10 @@ func InitProviderAndLoadCommonSettingsForTest(extraConfigs ...string) {
|
||||
if err := PrepareAppDataPath(); err != nil {
|
||||
log.Fatal("Can not prepare APP_DATA_PATH: %v", err)
|
||||
}
|
||||
// register the dummy hash algorithm function used in the test fixtures
|
||||
_ = hash.Register("dummy", hash.NewDummyHasher)
|
||||
|
||||
PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
|
||||
}
|
||||
|
||||
// newFileProviderFromConf initializes configuration context.
|
||||
|
@ -3,15 +3,16 @@
|
||||
|
||||
package setting
|
||||
|
||||
// FIXME: DEPRECATED to be removed in v1.18.0
|
||||
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version
|
||||
// if these are removed, the warning will not be shown
|
||||
// - will need to set default for [queue.task] LENGTH to 1000 though
|
||||
func loadTaskFrom(rootCfg ConfigProvider) {
|
||||
taskSec := rootCfg.Section("task")
|
||||
queueTaskSec := rootCfg.Section("queue.task")
|
||||
|
||||
deprecatedSetting(rootCfg, "task", "QUEUE_TYPE", "queue.task", "TYPE")
|
||||
deprecatedSetting(rootCfg, "task", "QUEUE_CONN_STR", "queue.task", "CONN_STR")
|
||||
deprecatedSetting(rootCfg, "task", "QUEUE_LENGTH", "queue.task", "LENGTH")
|
||||
deprecatedSetting(rootCfg, "task", "QUEUE_TYPE", "queue.task", "TYPE", "v1.19.0")
|
||||
deprecatedSetting(rootCfg, "task", "QUEUE_CONN_STR", "queue.task", "CONN_STR", "v1.19.0")
|
||||
deprecatedSetting(rootCfg, "task", "QUEUE_LENGTH", "queue.task", "LENGTH", "v1.19.0")
|
||||
|
||||
switch taskSec.Key("QUEUE_TYPE").MustString("channel") {
|
||||
case "channel":
|
||||
|
@ -11,10 +11,11 @@ import (
|
||||
// AccessToken represents an API access token.
|
||||
// swagger:response AccessToken
|
||||
type AccessToken struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Token string `json:"sha1"`
|
||||
TokenLastEight string `json:"token_last_eight"`
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Token string `json:"sha1"`
|
||||
TokenLastEight string `json:"token_last_eight"`
|
||||
Scopes []string `json:"scopes"`
|
||||
}
|
||||
|
||||
// AccessTokenList represents a list of API access token.
|
||||
@ -22,9 +23,10 @@ type AccessToken struct {
|
||||
type AccessTokenList []*AccessToken
|
||||
|
||||
// CreateAccessTokenOption options when create access token
|
||||
// swagger:parameters userCreateToken
|
||||
type CreateAccessTokenOption struct {
|
||||
Name string `json:"name" binding:"Required"`
|
||||
// required: true
|
||||
Name string `json:"name" binding:"Required"`
|
||||
Scopes []string `json:"scopes"`
|
||||
}
|
||||
|
||||
// CreateOAuth2ApplicationOptions holds options to create an oauth2 application
|
||||
|
@ -757,6 +757,7 @@ access_token_deletion_confirm_action = Delete
|
||||
access_token_deletion_desc = Deleting a token will revoke access to your account for applications using it. This cannot be undone. Continue?
|
||||
delete_token_success = The token has been deleted. Applications using it no longer have access to your account.
|
||||
select_scopes = Select scopes
|
||||
scopes_list = Scopes:
|
||||
|
||||
manage_oauth2_applications = Manage OAuth2 Applications
|
||||
edit_oauth2_application = Edit OAuth2 Application
|
||||
@ -2152,6 +2153,7 @@ settings.choose_branch = Choose a branch…
|
||||
settings.no_protected_branch = There are no protected branches.
|
||||
settings.edit_protected_branch = Edit
|
||||
settings.protected_branch_required_rule_name = Required rule name
|
||||
settings.protected_branch_duplicate_rule_name = Duplicate rule name
|
||||
settings.protected_branch_required_approvals_min = Required approvals cannot be negative.
|
||||
settings.tags = Tags
|
||||
settings.tags.protection = Tag Protection
|
||||
|
@ -1420,8 +1420,9 @@ func GetPullRequestFiles(ctx *context.APIContext) {
|
||||
startCommitID := prInfo.MergeBase
|
||||
endCommitID := headCommitID
|
||||
|
||||
maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles
|
||||
maxLines := setting.Git.MaxGitDiffLines
|
||||
|
||||
// FIXME: If there are too many files in the repo, may cause some unpredictable issues.
|
||||
diff, err := gitdiff.GetDiff(baseGitRepo,
|
||||
&gitdiff.DiffOptions{
|
||||
BeforeCommitID: startCommitID,
|
||||
@ -1429,7 +1430,7 @@ func GetPullRequestFiles(ctx *context.APIContext) {
|
||||
SkipTo: ctx.FormString("skip-to"),
|
||||
MaxLines: maxLines,
|
||||
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
|
||||
MaxFiles: maxFiles,
|
||||
MaxFiles: -1, // GetDiff() will return all files
|
||||
WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.FormString("whitespace")),
|
||||
})
|
||||
if err != nil {
|
||||
@ -1452,6 +1453,7 @@ func GetPullRequestFiles(ctx *context.APIContext) {
|
||||
if lenFiles < 0 {
|
||||
lenFiles = 0
|
||||
}
|
||||
|
||||
apiFiles := make([]*api.ChangedFile, 0, lenFiles)
|
||||
for i := start; i < end; i++ {
|
||||
apiFiles = append(apiFiles, convert.ToChangedFile(diff.Files[i], pr.HeadRepo, endCommitID))
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
@ -62,6 +63,7 @@ func ListAccessTokens(ctx *context.APIContext) {
|
||||
ID: tokens[i].ID,
|
||||
Name: tokens[i].Name,
|
||||
TokenLastEight: tokens[i].TokenLastEight,
|
||||
Scopes: tokens[i].Scope.StringSlice(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,9 +84,9 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: username of user
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: userCreateToken
|
||||
// type: string
|
||||
// - name: body
|
||||
// in: body
|
||||
// schema:
|
||||
// "$ref": "#/definitions/CreateAccessTokenOption"
|
||||
@ -111,6 +113,13 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
scope, err := auth_model.AccessTokenScope(strings.Join(form.Scopes, ",")).Normalize()
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusBadRequest, "AccessTokenScope.Normalize", fmt.Errorf("invalid access token scope provided: %w", err))
|
||||
return
|
||||
}
|
||||
t.Scope = scope
|
||||
|
||||
if err := auth_model.NewAccessToken(t); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "NewAccessToken", err)
|
||||
return
|
||||
|
@ -166,10 +166,36 @@ func SettingsProtectedBranchPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
var err error
|
||||
protectBranch, err = git_model.GetProtectedBranchRuleByName(ctx, ctx.Repo.Repository.ID, f.RuleName)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProtectBranchOfRepoByName", err)
|
||||
return
|
||||
if f.RuleID > 0 {
|
||||
// If the RuleID isn't 0, it must be an edit operation. So we get rule by id.
|
||||
protectBranch, err = git_model.GetProtectedBranchRuleByID(ctx, ctx.Repo.Repository.ID, f.RuleID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProtectBranchOfRepoByID", err)
|
||||
return
|
||||
}
|
||||
if protectBranch != nil && protectBranch.RuleName != f.RuleName {
|
||||
// RuleName changed. We need to check if there is a rule with the same name.
|
||||
// If a rule with the same name exists, an error should be returned.
|
||||
sameNameProtectBranch, err := git_model.GetProtectedBranchRuleByName(ctx, ctx.Repo.Repository.ID, f.RuleName)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProtectBranchOfRepoByName", err)
|
||||
return
|
||||
}
|
||||
if sameNameProtectBranch != nil {
|
||||
ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_duplicate_rule_name"))
|
||||
ctx.Redirect(fmt.Sprintf("%s/settings/branches/edit?rule_name=%s", ctx.Repo.RepoLink, protectBranch.RuleName))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FIXME: If a new ProtectBranch has a duplicate RuleName, an error should be returned.
|
||||
// Currently, if a new ProtectBranch with a duplicate RuleName is created, the existing ProtectBranch will be updated.
|
||||
// But we cannot modify this logic now because many unit tests rely on it.
|
||||
protectBranch, err = git_model.GetProtectedBranchRuleByName(ctx, ctx.Repo.Repository.ID, f.RuleName)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProtectBranchOfRepoByName", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if protectBranch == nil {
|
||||
// No options found, create defaults.
|
||||
|
@ -190,6 +190,7 @@ func (f *RepoSettingForm) Validate(req *http.Request, errs binding.Errors) bindi
|
||||
// ProtectBranchForm form for changing protected branch settings
|
||||
type ProtectBranchForm struct {
|
||||
RuleName string `binding:"Required"`
|
||||
RuleID int64
|
||||
EnablePush string
|
||||
WhitelistUsers string
|
||||
WhitelistTeams string
|
||||
|
@ -150,7 +150,6 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *u
|
||||
log.Error("LoadPullRequest failed: %v", err)
|
||||
return
|
||||
}
|
||||
issue.PullRequest.Issue = issue
|
||||
apiPullRequest := &api.PullRequestPayload{
|
||||
Index: issue.Index,
|
||||
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
|
||||
@ -196,7 +195,6 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user
|
||||
log.Error("LoadPullRequest failed: %v", err)
|
||||
return
|
||||
}
|
||||
issue.PullRequest.Issue = issue
|
||||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
|
||||
Action: api.HookIssueEdited,
|
||||
Index: issue.Index,
|
||||
@ -328,7 +326,10 @@ func (m *webhookNotifier) NotifyIssueChangeContent(ctx context.Context, doer *us
|
||||
mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo)
|
||||
var err error
|
||||
if issue.IsPull {
|
||||
issue.PullRequest.Issue = issue
|
||||
if err := issue.LoadPullRequest(ctx); err != nil {
|
||||
log.Error("LoadPullRequest: %v", err)
|
||||
return
|
||||
}
|
||||
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
|
||||
Action: api.HookIssueEdited,
|
||||
Index: issue.Index,
|
||||
|
@ -39,6 +39,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui two wide column center">
|
||||
{{if $.IsOrganizationOwner}}
|
||||
<div class="meta">
|
||||
{{$.locale.Tr "admin.users.2fa"}}
|
||||
</div>
|
||||
@ -51,6 +52,7 @@
|
||||
{{end}}
|
||||
</strong>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="ui three wide column">
|
||||
|
@ -58,7 +58,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $t, $unit := $.Units}}
|
||||
{{if and (lt $unit.MaxPerm 2) (not $unit.Type.UnitGlobalDisabled)}}
|
||||
{{if (not $unit.Type.UnitGlobalDisabled)}}
|
||||
<tr>
|
||||
<td><strong>{{$.locale.Tr $unit.NameKey}}</strong></td>
|
||||
<td>{{if eq ($.Team.UnitAccessMode $.Context $unit.Type) 0 -}}
|
||||
|
@ -17,7 +17,7 @@
|
||||
{{$class = (printf "%s%s" $class " isWarning")}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="ui top attached header clearing segment gt-pr commit-header {{$class}}">
|
||||
<div class="ui top attached header clearing segment gt-relative commit-header {{$class}}">
|
||||
<div class="gt-df gt-mb-4 gt-fw">
|
||||
<h3 class="gt-mb-0 gt-f1"><span class="commit-summary" title="{{.Commit.Summary}}">{{RenderCommitMessage $.Context .Commit.Message $.RepoLink $.Repository.ComposeMetas}}</span>{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses "root" $}}</h3>
|
||||
{{if not $.PageIsWiki}}
|
||||
|
@ -1,6 +1,14 @@
|
||||
{{if eq (len .Statuses) 1}}{{$status := index .Statuses 0}}{{if $status.TargetURL}}<a class="ui link commit-statuses-trigger gt-vm" href="{{$status.TargetURL}}">{{template "repo/commit_status" .Status}}</a>{{end}}{{end}}
|
||||
<div class="ui commit-statuses-popup commit-statuses tippy-target">
|
||||
<div class="ui relaxed list divided">
|
||||
{{if .Statuses}}
|
||||
{{if and (eq (len .Statuses) 1) .Status.TargetURL}}
|
||||
<a class="gt-vm gt-tdn" data-tippy="commit-statuses" href="{{.Status.TargetURL}}">
|
||||
{{template "repo/commit_status" .Status}}
|
||||
</a>
|
||||
{{else}}
|
||||
<span class="gt-vm" data-tippy="commit-statuses" tabindex="0">
|
||||
{{template "repo/commit_status" .Status}}
|
||||
</span>
|
||||
{{end}}
|
||||
<div class="tippy-target ui relaxed list divided">
|
||||
{{range .Statuses}}
|
||||
<div class="ui item singular-status gt-df">
|
||||
{{template "repo/commit_status" .}}
|
||||
@ -11,4 +19,4 @@
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
@ -61,7 +61,7 @@
|
||||
{{$.locale.Tr "repo.pulls.title_desc" .NumCommits $headHref $baseHref | Safe}}
|
||||
</span>
|
||||
{{end}}
|
||||
<span id="pull-desc-edit gt-hidden">
|
||||
<span id="pull-desc-edit" class="gt-hidden">
|
||||
<div class="ui floating filter dropdown">
|
||||
<div class="ui basic small button">
|
||||
<span class="text">{{.locale.Tr "repo.pulls.compare_compare"}}: {{$.HeadTarget}}</span>
|
||||
|
@ -14084,14 +14084,13 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"x-go-name": "Name",
|
||||
"description": "username of user",
|
||||
"name": "username",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "userCreateToken",
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/CreateAccessTokenOption"
|
||||
@ -14194,6 +14193,13 @@
|
||||
"type": "string",
|
||||
"x-go-name": "Name"
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Scopes"
|
||||
},
|
||||
"sha1": {
|
||||
"type": "string",
|
||||
"x-go-name": "Token"
|
||||
@ -14925,10 +14931,20 @@
|
||||
"CreateAccessTokenOption": {
|
||||
"description": "CreateAccessTokenOption options when create access token",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"x-go-name": "Name"
|
||||
},
|
||||
"scopes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Scopes"
|
||||
}
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||
|
@ -21,7 +21,14 @@
|
||||
</div>
|
||||
<i class="icon tooltip{{if .HasRecentActivity}} green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.token_state_desc"}}"{{end}}>{{svg "fontawesome-send" 36}}</i>
|
||||
<div class="content">
|
||||
<strong>{{.Name}}</strong>
|
||||
<details><summary><strong>{{.Name}}</strong></summary>
|
||||
<p class="gt-my-2">{{$.locale.Tr "settings.scopes_list"}}</p>
|
||||
<ul class="gt-my-2">
|
||||
{{range .Scope.StringSlice}}
|
||||
<li>{{.}}</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</details>
|
||||
<div class="activity meta">
|
||||
<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span> — {{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
|
||||
</div>
|
||||
|
@ -630,8 +630,17 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
|
||||
|
||||
commitID := path.Base(commitURL)
|
||||
|
||||
addCommitStatus := func(status api.CommitStatusState) func(*testing.T) {
|
||||
return doAPICreateCommitStatus(ctx, commitID, api.CreateStatusOption{
|
||||
State: status,
|
||||
TargetURL: "http://test.ci/",
|
||||
Description: "",
|
||||
Context: "testci",
|
||||
})
|
||||
}
|
||||
|
||||
// Call API to add Pending status for commit
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, commitID, api.CommitStatusPending))
|
||||
t.Run("CreateStatus", addCommitStatus(api.CommitStatusPending))
|
||||
|
||||
// Cancel not existing auto merge
|
||||
ctx.ExpectedCode = http.StatusNotFound
|
||||
@ -660,7 +669,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
|
||||
assert.False(t, pr.HasMerged)
|
||||
|
||||
// Call API to add Failure status for commit
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, commitID, api.CommitStatusFailure))
|
||||
t.Run("CreateStatus", addCommitStatus(api.CommitStatusFailure))
|
||||
|
||||
// Check pr status
|
||||
pr, err = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t)
|
||||
@ -668,7 +677,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
|
||||
assert.False(t, pr.HasMerged)
|
||||
|
||||
// Call API to add Success status for commit
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, commitID, api.CommitStatusSuccess))
|
||||
t.Run("CreateStatus", addCommitStatus(api.CommitStatusSuccess))
|
||||
|
||||
// wait to let gitea merge stuff
|
||||
time.Sleep(time.Second)
|
||||
|
@ -70,7 +70,12 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||
for _, status := range statusList {
|
||||
|
||||
// Call API to add status for commit
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(testCtx, commitID, status))
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(testCtx, commitID, api.CreateStatusOption{
|
||||
State: status,
|
||||
TargetURL: "http://test.ci/",
|
||||
Description: "",
|
||||
Context: "testci",
|
||||
}))
|
||||
|
||||
req = NewRequestf(t, "GET", "/user1/repo1/pulls/1/commits")
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
@ -88,15 +93,13 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func doAPICreateCommitStatus(ctx APITestContext, commitID string, status api.CommitStatusState) func(*testing.T) {
|
||||
func doAPICreateCommitStatus(ctx APITestContext, commitID string, data api.CreateStatusOption) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/statuses/%s?token=%s", ctx.Username, ctx.Reponame, commitID, ctx.Token),
|
||||
api.CreateStatusOption{
|
||||
State: status,
|
||||
TargetURL: "http://test.ci/",
|
||||
Description: "",
|
||||
Context: "testci",
|
||||
},
|
||||
req := NewRequestWithJSON(
|
||||
t,
|
||||
http.MethodPost,
|
||||
fmt.Sprintf("/api/v1/repos/%s/%s/statuses/%s?token=%s", ctx.Username, ctx.Reponame, commitID, ctx.Token),
|
||||
data,
|
||||
)
|
||||
if ctx.ExpectedCode != 0 {
|
||||
ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
|
||||
|
@ -52,14 +52,19 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
||||
|
||||
// Call API to add status for commit
|
||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CommitStatusState(state)))
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
||||
State: api.CommitStatusState(state),
|
||||
TargetURL: "http://test.ci/",
|
||||
Description: "",
|
||||
Context: "testci",
|
||||
}))
|
||||
|
||||
req = NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc = NewHTMLParser(t, resp.Body)
|
||||
// Check if commit status is displayed in message column
|
||||
sel := doc.doc.Find("#commits-table tbody tr td.message a.commit-statuses-trigger .commit-status")
|
||||
// Check if commit status is displayed in message column (.tippy-target to ignore the tippy trigger)
|
||||
sel := doc.doc.Find("#commits-table tbody tr td.message .tippy-target .commit-status")
|
||||
assert.Equal(t, 1, sel.Length())
|
||||
for _, class := range classes {
|
||||
assert.True(t, sel.HasClass(class))
|
||||
@ -145,7 +150,12 @@ func TestRepoCommitsStatusParallel(t *testing.T) {
|
||||
go func(parentT *testing.T, i int) {
|
||||
parentT.Run(fmt.Sprintf("ParallelCreateStatus_%d", i), func(t *testing.T) {
|
||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepoStatus)
|
||||
runBody := doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CommitStatusState("pending"))
|
||||
runBody := doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
||||
State: api.CommitStatusPending,
|
||||
TargetURL: "http://test.ci/",
|
||||
Description: "",
|
||||
Context: "testci",
|
||||
})
|
||||
runBody(t)
|
||||
wg.Done()
|
||||
})
|
||||
@ -153,3 +163,43 @@ func TestRepoCommitsStatusParallel(t *testing.T) {
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestRepoCommitsStatusMultiple(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
// Request repository commits page
|
||||
req := NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
// Get first commit URL
|
||||
commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
|
||||
// Call API to add status for commit
|
||||
ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeRepo)
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
||||
State: api.CommitStatusSuccess,
|
||||
TargetURL: "http://test.ci/",
|
||||
Description: "",
|
||||
Context: "testci",
|
||||
}))
|
||||
|
||||
t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
|
||||
State: api.CommitStatusSuccess,
|
||||
TargetURL: "http://test.ci/",
|
||||
Description: "",
|
||||
Context: "other_context",
|
||||
}))
|
||||
|
||||
req = NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc = NewHTMLParser(t, resp.Body)
|
||||
// Check that the data-tippy="commit-statuses" (for trigger) and commit-status (svg) are present
|
||||
sel := doc.doc.Find("#commits-table tbody tr td.message [data-tippy=\"commit-statuses\"] .commit-status")
|
||||
assert.Equal(t, 1, sel.Length())
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ export function initRepoCommitLastCommitLoader() {
|
||||
}
|
||||
|
||||
export function initCommitStatuses() {
|
||||
$('.commit-statuses-trigger').each(function () {
|
||||
$('[data-tippy="commit-statuses"]').each(function () {
|
||||
const top = $('.repository.file.list').length > 0 || $('.repository.diff').length > 0;
|
||||
|
||||
createTippy(this, {
|
||||
|
@ -552,8 +552,6 @@ export function initRepoIssueReferenceIssue() {
|
||||
// Reference issue
|
||||
$(document).on('click', '.reference-issue', function (event) {
|
||||
const $this = $(this);
|
||||
$this.closest('.dropdown').find('.menu').toggle('visible'); // eslint-disable-line
|
||||
|
||||
const content = $(`#${$this.data('target')}`).text();
|
||||
const poster = $this.data('poster-username');
|
||||
const reference = $this.data('reference');
|
||||
|
@ -291,7 +291,6 @@ export function initRepoCommentForm() {
|
||||
async function onEditContent(event) {
|
||||
event.preventDefault();
|
||||
|
||||
$(this).closest('.dropdown').find('.menu').toggle('visible'); // eslint-disable-line
|
||||
const $segment = $(this).closest('.header').next();
|
||||
const $editContentZone = $segment.find('.edit-content-zone');
|
||||
const $renderContent = $segment.find('.render-content');
|
||||
@ -584,7 +583,6 @@ function initRepoIssueCommentEdit() {
|
||||
|
||||
// Quote reply
|
||||
$(document).on('click', '.quote-reply', function (event) {
|
||||
$(this).closest('.dropdown').find('.menu').toggle('visible'); // eslint-disable-line
|
||||
const target = $(this).data('target');
|
||||
const quote = $(`#${target}`).text().replace(/\n/g, '\n> ');
|
||||
const content = `> ${quote}\n\n`;
|
||||
|
@ -340,8 +340,7 @@ a.label,
|
||||
.ui.search .results a,
|
||||
.ui .menu a,
|
||||
.ui.cards a.card,
|
||||
.issue-keyword a,
|
||||
a.commit-statuses-trigger {
|
||||
.issue-keyword a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,4 @@
|
||||
.repository {
|
||||
.popup.commit-statuses {
|
||||
// we had better limit the max size of the popup, and add scroll bars if the content size is too large.
|
||||
// otherwise some part of the popup will be hidden by viewport boundary
|
||||
max-height: 45vh;
|
||||
max-width: 60vw;
|
||||
|
||||
&.ui.right {
|
||||
// Override `.ui.attached.header .right:not(.dropdown) height: 30px;` which would otherwise lead to
|
||||
// the status popup box having its height fixed at 30px. See https://github.com/go-gitea/gitea/issues/18498
|
||||
height: auto;
|
||||
}
|
||||
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
|
||||
.list {
|
||||
padding: .8em; // to make the scrollbar align to the border, we move the padding from outer `.popup` to this inside `.list`
|
||||
|
||||
> .item {
|
||||
line-height: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.repo-header {
|
||||
.ui.compact.menu {
|
||||
margin-left: 1rem;
|
||||
|
@ -2,7 +2,6 @@
|
||||
.gt-di { display: inline !important; }
|
||||
.gt-dif { display: inline-flex !important; }
|
||||
.gt-dib { display: inline-block !important; }
|
||||
.gt-pr { position: relative !important; }
|
||||
.gt-ac { align-items: center !important; }
|
||||
.gt-tc { text-align: center !important; }
|
||||
.gt-tl { text-align: left !important; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user