mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-13 19:16:11 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afa7f22dd8 | ||
|
|
182be90655 | ||
|
|
4a738a8f16 | ||
|
|
206b66a184 | ||
|
|
205be63bc1 | ||
|
|
bf1441b1e1 | ||
|
|
fae18bdac0 | ||
|
|
661e3e2bdc | ||
|
|
70038719bf | ||
|
|
55d7e53d99 | ||
|
|
96d41287e5 | ||
|
|
df11075389 | ||
|
|
b8a2cd9f40 | ||
|
|
4f296f7436 | ||
|
|
78b9ef3586 | ||
|
|
90dfe445c2 | ||
|
|
a728d1e046 | ||
|
|
7f85728cf9 | ||
|
|
d2b308ae35 | ||
|
|
8e8e8ee150 | ||
|
|
05ee88e576 | ||
|
|
0d7cb2323f | ||
|
|
5cdffc2b0c | ||
|
|
a0101c61a4 | ||
|
|
c0b1197a64 | ||
|
|
e39ed0b1d9 | ||
|
|
cb24cbc1fc | ||
|
|
584d01cf2c | ||
|
|
798fdeae45 | ||
|
|
87997cccbb | ||
|
|
0d5111c5c3 | ||
|
|
10fff12da4 | ||
|
|
0d43a2a069 | ||
|
|
8396b792f8 |
36
CHANGELOG.md
36
CHANGELOG.md
@@ -4,6 +4,42 @@ 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.13.1](https://github.com/go-gitea/gitea/releases/tag/v1.13.1) - 2020-12-29
|
||||
|
||||
* SECURITY
|
||||
* Hide private participation in Orgs (#13994) (#14031)
|
||||
* Fix escaping issue in diff (#14153) (#14154)
|
||||
* BUGFIXES
|
||||
* Fix bug of link query order on markdown render (#14156) (#14171)
|
||||
* Drop long repo topics during migration (#14152) (#14155)
|
||||
* Ensure that search term and page are not lost on adoption page-turn (#14133) (#14143)
|
||||
* Fix storage config implementation (#14091) (#14095)
|
||||
* Fix panic in BasicAuthDecode (#14046) (#14048)
|
||||
* Always wait for the cmd to finish (#14006) (#14039)
|
||||
* Don't use simpleMDE editor on mobile devices for 1.13 (#14029)
|
||||
* Fix incorrect review comment diffs (#14002) (#14011)
|
||||
* Trim the branch prefix from action.GetBranch (#13981) (#13986)
|
||||
* Ensure template renderer is available before storage handler (#13164) (#13982)
|
||||
* Whenever the password is updated ensure that the hash algorithm is too (#13966) (#13967)
|
||||
* Enforce setting HEAD in wiki to master (#13950) (#13961)
|
||||
* Fix feishu webhook caused by API changed (#13938)
|
||||
* Fix Quote Reply button on review diff (#13830) (#13898)
|
||||
* Fix Pull Merge when tag with same name as base branch exist (#13882) (#13896)
|
||||
* Fix mermaid chart size (#13865)
|
||||
* Fix branch/tag notifications in mirror sync (#13855) (#13862)
|
||||
* Fix crash in short link processor (#13839) (#13841)
|
||||
* Update font stack to bootstrap's latest (#13834) (#13837)
|
||||
* Make sure email recipients can see issue (#13820) (#13827)
|
||||
* Reply button is not removed when deleting a code review comment (#13824)
|
||||
* When reinitialising DBConfig reset the database use flags (#13796) (#13811)
|
||||
* ENHANCEMENTS
|
||||
* Add emoji in label to project boards (#13978) (#14021)
|
||||
* Send webhook when tag is removed via Web UI (#14015) (#14019)
|
||||
* Use Process Manager to create own Context (#13792) (#13793)
|
||||
* API
|
||||
* GetCombinedCommitStatusByRef always return json & swagger doc fixes (#14047)
|
||||
* Return original URL of Repositories (#13885) (#13886)
|
||||
|
||||
## [1.13.0](https://github.com/go-gitea/gitea/releases/tag/v1.13.0) - 2020-12-01
|
||||
* SECURITY
|
||||
* Add Allow-/Block-List for Migrate & Mirrors (#13610) (#13776)
|
||||
|
||||
@@ -283,7 +283,7 @@ func runChangePassword(c *cli.Context) error {
|
||||
}
|
||||
user.HashPassword(c.String("password"))
|
||||
|
||||
if err := models.UpdateUserCols(user, "passwd", "salt"); err != nil {
|
||||
if err := models.UpdateUserCols(user, "passwd", "passwd_hash_algo", "salt"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
4
go.mod
4
go.mod
@@ -104,7 +104,7 @@ require (
|
||||
github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60
|
||||
go.jolheiser.com/hcaptcha v0.0.4
|
||||
go.jolheiser.com/pwn v0.0.3
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff
|
||||
@@ -124,3 +124,5 @@ require (
|
||||
)
|
||||
|
||||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.2.4
|
||||
|
||||
replace github.com/microcosm-cc/bluemonday => github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8
|
||||
|
||||
10
go.sum
10
go.sum
@@ -598,6 +598,8 @@ github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.8.1-0.20200908161135-083382b7e6fc h1:ERSU1OvZ6MdWhHieo2oT7xwR/HCksqKdgK6iYPU5pHI=
|
||||
github.com/lib/pq v1.8.1-0.20200908161135-083382b7e6fc/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8 h1:1omo92DLtxQu6VwVPSZAmduHaK5zssed6cvkHyl1XOg=
|
||||
github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY=
|
||||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:mmIfjCSQlGYXmJ95jFN84AkQFnVABtKuJL8IrzwvUKQ=
|
||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk=
|
||||
@@ -649,8 +651,6 @@ github.com/mgechev/revive v1.0.3-0.20200921231451-246eac737dc7 h1:ydVkpU/M4/c45y
|
||||
github.com/mgechev/revive v1.0.3-0.20200921231451-246eac737dc7/go.mod h1:no/hfevHbndpXR5CaJahkYCfM/FFpmM/dSOwFGU7Z1o=
|
||||
github.com/mholt/archiver/v3 v3.3.0 h1:vWjhY8SQp5yzM9P6OJ/eZEkmi3UAbRrxCq48MxjAzig=
|
||||
github.com/mholt/archiver/v3 v3.3.0/go.mod h1:YnQtqsp+94Rwd0D/rk5cnLrxusUBUXg+08Ebtr1Mqao=
|
||||
github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912 h1:hJde9rA24hlTcAYSwJoXpDUyGtfKQ/jsofw+WaDqGrI=
|
||||
github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
@@ -937,8 +937,9 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -1053,6 +1054,8 @@ golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff h1:1CPUrky56AcgSpxz/KfgzQWzfG09u5YOL8MvPYBlrL8=
|
||||
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
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=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
@@ -1197,6 +1200,7 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
mvdan.cc/xurls/v2 v2.2.0 h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A=
|
||||
mvdan.cc/xurls/v2 v2.2.0/go.mod h1:EV1RMtya9D6G5DMYPGD8zTQzaHet6Jh8gFlRgGRJeO8=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
|
||||
|
||||
@@ -111,7 +111,7 @@ func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL), prepare ...bo
|
||||
|
||||
func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
assert.NoError(t, git.CloneWithArgs(u.String(), dstLocalPath, allowLFSFilters(), git.CloneRepoOptions{}))
|
||||
assert.NoError(t, git.CloneWithArgs(context.Background(), u.String(), dstLocalPath, allowLFSFilters(), git.CloneRepoOptions{}))
|
||||
assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
@@ -243,7 +244,7 @@ func (a *Action) getCommentLink(e Engine) string {
|
||||
|
||||
// GetBranch returns the action's repository branch.
|
||||
func (a *Action) GetBranch() string {
|
||||
return a.RefName
|
||||
return strings.TrimPrefix(a.RefName, git.BranchPrefix)
|
||||
}
|
||||
|
||||
// GetContent returns the action's content.
|
||||
|
||||
@@ -119,8 +119,18 @@ func InitOAuth2() error {
|
||||
if err := oauth2.Init(x); err != nil {
|
||||
return err
|
||||
}
|
||||
loginSources, _ := GetActiveOAuth2ProviderLoginSources()
|
||||
return initOAuth2LoginSources()
|
||||
}
|
||||
|
||||
// ResetOAuth2 clears existing OAuth2 providers and loads them from DB
|
||||
func ResetOAuth2() error {
|
||||
oauth2.ClearProviders()
|
||||
return initOAuth2LoginSources()
|
||||
}
|
||||
|
||||
// initOAuth2LoginSources is used to load and register all active OAuth2 providers
|
||||
func initOAuth2LoginSources() error {
|
||||
loginSources, _ := GetActiveOAuth2ProviderLoginSources()
|
||||
for _, source := range loginSources {
|
||||
oAuth2Config := source.OAuth2()
|
||||
err := oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping)
|
||||
|
||||
@@ -426,6 +426,7 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool)
|
||||
HTMLURL: repo.HTMLURL(),
|
||||
SSHURL: cloneLink.SSH,
|
||||
CloneURL: cloneLink.HTTPS,
|
||||
OriginalURL: repo.SanitizedOriginalURL(),
|
||||
Website: repo.Website,
|
||||
Stars: repo.NumStars,
|
||||
Forks: repo.NumForks,
|
||||
|
||||
@@ -551,6 +551,7 @@ func (u *User) GetOwnedOrganizations() (err error) {
|
||||
}
|
||||
|
||||
// GetOrganizations returns paginated organizations that user belongs to.
|
||||
// TODO: does not respect All and show orgs you privately participate
|
||||
func (u *User) GetOrganizations(opts *SearchOrganizationsOptions) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
@@ -118,6 +118,11 @@ func RemoveProvider(providerName string) {
|
||||
delete(goth.GetProviders(), providerName)
|
||||
}
|
||||
|
||||
// ClearProviders clears all OAuth2 providers from the goth lib
|
||||
func ClearProviders() {
|
||||
goth.ClearProviders()
|
||||
}
|
||||
|
||||
// used to create different types of goth providers
|
||||
func createProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL string, customURLMapping *CustomURLMapping) (goth.Provider, error) {
|
||||
callbackURL := setting.AppURL + "user/oauth2/" + url.PathEscape(providerName) + "/callback"
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -65,6 +66,11 @@ func BasicAuthDecode(encoded string) (string, string, error) {
|
||||
}
|
||||
|
||||
auth := strings.SplitN(string(s), ":", 2)
|
||||
|
||||
if len(auth) != 2 {
|
||||
return "", "", errors.New("invalid basic authentication")
|
||||
}
|
||||
|
||||
return auth[0], auth[1], nil
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,12 @@ func TestBasicAuthDecode(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "foo", user)
|
||||
assert.Equal(t, "bar", pass)
|
||||
|
||||
_, _, err = BasicAuthDecode("aW52YWxpZA==")
|
||||
assert.Error(t, err)
|
||||
|
||||
_, _, err = BasicAuthDecode("invalid")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestBasicAuthEncode(t *testing.T) {
|
||||
|
||||
@@ -153,6 +153,7 @@ func (c *Command) RunInDirTimeoutEnvFullPipelineFunc(env []string, timeout time.
|
||||
err := fn(ctx, cancel)
|
||||
if err != nil {
|
||||
cancel()
|
||||
_ = cmd.Wait()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ var (
|
||||
GitExecutable = "git"
|
||||
|
||||
// DefaultContext is the default context to run git commands in
|
||||
// will be overwritten by Init with HammerContext
|
||||
DefaultContext = context.Background()
|
||||
|
||||
gitVersion *version.Version
|
||||
|
||||
@@ -8,6 +8,7 @@ package git
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -166,19 +167,24 @@ type CloneRepoOptions struct {
|
||||
|
||||
// Clone clones original repository to target path.
|
||||
func Clone(from, to string, opts CloneRepoOptions) (err error) {
|
||||
return CloneWithContext(DefaultContext, from, to, opts)
|
||||
}
|
||||
|
||||
// CloneWithContext clones original repository to target path.
|
||||
func CloneWithContext(ctx context.Context, from, to string, opts CloneRepoOptions) (err error) {
|
||||
cargs := make([]string, len(GlobalCommandArgs))
|
||||
copy(cargs, GlobalCommandArgs)
|
||||
return CloneWithArgs(from, to, cargs, opts)
|
||||
return CloneWithArgs(ctx, from, to, cargs, opts)
|
||||
}
|
||||
|
||||
// CloneWithArgs original repository to target path.
|
||||
func CloneWithArgs(from, to string, args []string, opts CloneRepoOptions) (err error) {
|
||||
func CloneWithArgs(ctx context.Context, from, to string, args []string, opts CloneRepoOptions) (err error) {
|
||||
toDir := path.Dir(to)
|
||||
if err = os.MkdirAll(toDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := NewCommandNoGlobals(args...).AddArguments("clone")
|
||||
cmd := NewCommandContextNoGlobals(ctx, args...).AddArguments("clone")
|
||||
if opts.Mirror {
|
||||
cmd.AddArguments("--mirror")
|
||||
}
|
||||
|
||||
@@ -632,16 +632,18 @@ func shortLinkProcessorFull(ctx *postProcessCtx, node *html.Node, noLink bool) {
|
||||
// When parsing HTML, x/net/html will change all quotes which are
|
||||
// not used for syntax into UTF-8 quotes. So checking val[0] won't
|
||||
// be enough, since that only checks a single byte.
|
||||
if (strings.HasPrefix(val, "“") && strings.HasSuffix(val, "”")) ||
|
||||
(strings.HasPrefix(val, "‘") && strings.HasSuffix(val, "’")) {
|
||||
const lenQuote = len("‘")
|
||||
val = val[lenQuote : len(val)-lenQuote]
|
||||
} else if (strings.HasPrefix(val, "\"") && strings.HasSuffix(val, "\"")) ||
|
||||
(strings.HasPrefix(val, "'") && strings.HasSuffix(val, "'")) {
|
||||
val = val[1 : len(val)-1]
|
||||
} else if strings.HasPrefix(val, "'") && strings.HasSuffix(val, "’") {
|
||||
const lenQuote = len("‘")
|
||||
val = val[1 : len(val)-lenQuote]
|
||||
if len(val) > 1 {
|
||||
if (strings.HasPrefix(val, "“") && strings.HasSuffix(val, "”")) ||
|
||||
(strings.HasPrefix(val, "‘") && strings.HasSuffix(val, "’")) {
|
||||
const lenQuote = len("‘")
|
||||
val = val[lenQuote : len(val)-lenQuote]
|
||||
} else if (strings.HasPrefix(val, "\"") && strings.HasSuffix(val, "\"")) ||
|
||||
(strings.HasPrefix(val, "'") && strings.HasSuffix(val, "'")) {
|
||||
val = val[1 : len(val)-1]
|
||||
} else if strings.HasPrefix(val, "'") && strings.HasSuffix(val, "’") {
|
||||
const lenQuote = len("‘")
|
||||
val = val[1 : len(val)-lenQuote]
|
||||
}
|
||||
}
|
||||
props[key] = val
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ func TestRender_links(t *testing.T) {
|
||||
`<p><a href="ftp://gitea.com/file.txt" rel="nofollow">ftp://gitea.com/file.txt</a></p>`)
|
||||
test(
|
||||
"magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download",
|
||||
`<p><a href="magnet:?dn=download&xt=urn%3Abtih%3A5dee65101db281ac9c46344cd6b175cdcadabcde" rel="nofollow">magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download</a></p>`)
|
||||
`<p><a href="magnet:?xt=urn%3Abtih%3A5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download" rel="nofollow">magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download</a></p>`)
|
||||
|
||||
// Test that should *not* be turned into URL
|
||||
test(
|
||||
|
||||
@@ -125,7 +125,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
|
||||
}
|
||||
r.DefaultBranch = repo.DefaultBranch
|
||||
|
||||
r, err = repository.MigrateRepositoryGitData(g.doer, owner, r, base.MigrateOptions{
|
||||
r, err = repository.MigrateRepositoryGitData(g.ctx, owner, r, base.MigrateOptions{
|
||||
RepoName: g.repoName,
|
||||
Description: repo.Description,
|
||||
OriginalURL: repo.OriginalURL,
|
||||
@@ -154,6 +154,15 @@ func (g *GiteaLocalUploader) Close() {
|
||||
|
||||
// CreateTopics creates topics
|
||||
func (g *GiteaLocalUploader) CreateTopics(topics ...string) error {
|
||||
// ignore topics to long for the db
|
||||
c := 0
|
||||
for i := range topics {
|
||||
if len(topics[i]) <= 25 {
|
||||
topics[c] = topics[i]
|
||||
c++
|
||||
}
|
||||
}
|
||||
topics = topics[:c]
|
||||
return models.SaveTopics(g.repo.ID, topics...)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
@@ -41,7 +42,7 @@ func WikiRemoteURL(remote string) string {
|
||||
}
|
||||
|
||||
// MigrateRepositoryGitData starts migrating git related data after created migrating repository
|
||||
func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opts migration.MigrateOptions) (*models.Repository, error) {
|
||||
func MigrateRepositoryGitData(ctx context.Context, u *models.User, repo *models.Repository, opts migration.MigrateOptions) (*models.Repository, error) {
|
||||
repoPath := models.RepoPath(u.Name, opts.RepoName)
|
||||
|
||||
if u.IsOrganization() {
|
||||
@@ -61,7 +62,7 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt
|
||||
return repo, fmt.Errorf("Failed to remove %s: %v", repoPath, err)
|
||||
}
|
||||
|
||||
if err = git.Clone(opts.CloneAddr, repoPath, git.CloneRepoOptions{
|
||||
if err = git.CloneWithContext(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{
|
||||
Mirror: true,
|
||||
Quiet: true,
|
||||
Timeout: migrateTimeout,
|
||||
@@ -77,7 +78,7 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt
|
||||
return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err)
|
||||
}
|
||||
|
||||
if err = git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{
|
||||
if err = git.CloneWithContext(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{
|
||||
Mirror: true,
|
||||
Quiet: true,
|
||||
Timeout: migrateTimeout,
|
||||
|
||||
@@ -62,6 +62,11 @@ func InitDBConfig() {
|
||||
sec := Cfg.Section("database")
|
||||
Database.Type = sec.Key("DB_TYPE").String()
|
||||
defaultCharset := "utf8"
|
||||
Database.UseMySQL = false
|
||||
Database.UseSQLite3 = false
|
||||
Database.UsePostgreSQL = false
|
||||
Database.UseMSSQL = false
|
||||
|
||||
switch Database.Type {
|
||||
case "sqlite3":
|
||||
Database.UseSQLite3 = true
|
||||
|
||||
@@ -31,22 +31,10 @@ func (s *Storage) MapTo(v interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getStorage(name, typ string, overrides ...*ini.Section) Storage {
|
||||
func getStorage(name, typ string, targetSec *ini.Section) Storage {
|
||||
const sectionName = "storage"
|
||||
sec := Cfg.Section(sectionName)
|
||||
|
||||
if len(overrides) == 0 {
|
||||
overrides = []*ini.Section{
|
||||
Cfg.Section(sectionName + "." + typ),
|
||||
Cfg.Section(sectionName + "." + name),
|
||||
}
|
||||
}
|
||||
|
||||
var storage Storage
|
||||
|
||||
storage.Type = sec.Key("STORAGE_TYPE").MustString(typ)
|
||||
storage.ServeDirect = sec.Key("SERVE_DIRECT").MustBool(false)
|
||||
|
||||
// Global Defaults
|
||||
sec.Key("MINIO_ENDPOINT").MustString("localhost:9000")
|
||||
sec.Key("MINIO_ACCESS_KEY_ID").MustString("")
|
||||
@@ -55,17 +43,37 @@ func getStorage(name, typ string, overrides ...*ini.Section) Storage {
|
||||
sec.Key("MINIO_LOCATION").MustString("us-east-1")
|
||||
sec.Key("MINIO_USE_SSL").MustBool(false)
|
||||
|
||||
storage.Section = sec
|
||||
var storage Storage
|
||||
storage.Section = targetSec
|
||||
storage.Type = typ
|
||||
|
||||
overrides := make([]*ini.Section, 0, 3)
|
||||
nameSec, err := Cfg.GetSection(sectionName + "." + name)
|
||||
if err == nil {
|
||||
overrides = append(overrides, nameSec)
|
||||
}
|
||||
|
||||
typeSec, err := Cfg.GetSection(sectionName + "." + typ)
|
||||
if err == nil {
|
||||
overrides = append(overrides, typeSec)
|
||||
nextType := typeSec.Key("STORAGE_TYPE").String()
|
||||
if len(nextType) > 0 {
|
||||
storage.Type = nextType // Support custom STORAGE_TYPE
|
||||
}
|
||||
}
|
||||
overrides = append(overrides, sec)
|
||||
|
||||
for _, override := range overrides {
|
||||
for _, key := range storage.Section.Keys() {
|
||||
if !override.HasKey(key.Name()) {
|
||||
_, _ = override.NewKey(key.Name(), key.Value())
|
||||
for _, key := range override.Keys() {
|
||||
if !targetSec.HasKey(key.Name()) {
|
||||
_, _ = targetSec.NewKey(key.Name(), key.Value())
|
||||
}
|
||||
}
|
||||
storage.ServeDirect = override.Key("SERVE_DIRECT").MustBool(false)
|
||||
storage.Section = override
|
||||
if len(storage.Type) == 0 {
|
||||
storage.Type = override.Key("STORAGE_TYPE").String()
|
||||
}
|
||||
}
|
||||
storage.ServeDirect = storage.Section.Key("SERVE_DIRECT").MustBool(false)
|
||||
|
||||
// Specific defaults
|
||||
storage.Path = storage.Section.Key("PATH").MustString(filepath.Join(AppDataPath, name))
|
||||
|
||||
197
modules/setting/storage_test.go
Normal file
197
modules/setting/storage_test.go
Normal file
@@ -0,0 +1,197 @@
|
||||
// Copyright 2020 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 setting
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
func Test_getStorageCustomType(t *testing.T) {
|
||||
iniStr := `
|
||||
[attachment]
|
||||
STORAGE_TYPE = my_minio
|
||||
MINIO_BUCKET = gitea-attachment
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ENDPOINT = my_minio:9000
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.EqualValues(t, "my_minio:9000", storage.Section.Key("MINIO_ENDPOINT").String())
|
||||
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
|
||||
func Test_getStorageNameSectionOverridesTypeSection(t *testing.T) {
|
||||
iniStr := `
|
||||
[attachment]
|
||||
STORAGE_TYPE = minio
|
||||
|
||||
[storage.attachments]
|
||||
MINIO_BUCKET = gitea-attachment
|
||||
|
||||
[storage.minio]
|
||||
MINIO_BUCKET = gitea
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
|
||||
func Test_getStorageTypeSectionOverridesStorageSection(t *testing.T) {
|
||||
iniStr := `
|
||||
[attachment]
|
||||
STORAGE_TYPE = minio
|
||||
|
||||
[storage.minio]
|
||||
MINIO_BUCKET = gitea-minio
|
||||
|
||||
[storage]
|
||||
MINIO_BUCKET = gitea
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.EqualValues(t, "gitea-minio", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
|
||||
func Test_getStorageSpecificOverridesStorage(t *testing.T) {
|
||||
iniStr := `
|
||||
[attachment]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_BUCKET = gitea-attachment
|
||||
|
||||
[storage.attachments]
|
||||
MINIO_BUCKET = gitea
|
||||
|
||||
[storage]
|
||||
STORAGE_TYPE = local
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
|
||||
func Test_getStorageGetDefaults(t *testing.T) {
|
||||
Cfg, _ = ini.Load([]byte(""))
|
||||
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "gitea", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
|
||||
func Test_getStorageMultipleName(t *testing.T) {
|
||||
iniStr := `
|
||||
[lfs]
|
||||
MINIO_BUCKET = gitea-lfs
|
||||
|
||||
[attachment]
|
||||
MINIO_BUCKET = gitea-attachment
|
||||
|
||||
[storage]
|
||||
MINIO_BUCKET = gitea-storage
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
{
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "gitea-attachment", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
{
|
||||
sec := Cfg.Section("lfs")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("lfs", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "gitea-lfs", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
{
|
||||
sec := Cfg.Section("avatar")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("avatars", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "gitea-storage", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getStorageUseOtherNameAsType(t *testing.T) {
|
||||
iniStr := `
|
||||
[attachment]
|
||||
STORAGE_TYPE = lfs
|
||||
|
||||
[storage.lfs]
|
||||
MINIO_BUCKET = gitea-storage
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
{
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "gitea-storage", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
{
|
||||
sec := Cfg.Section("lfs")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("lfs", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "gitea-storage", storage.Section.Key("MINIO_BUCKET").String())
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getStorageInheritStorageType(t *testing.T) {
|
||||
iniStr := `
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
}
|
||||
|
||||
func Test_getStorageInheritNameSectionType(t *testing.T) {
|
||||
iniStr := `
|
||||
[storage.attachments]
|
||||
STORAGE_TYPE = minio
|
||||
`
|
||||
Cfg, _ = ini.Load([]byte(iniStr))
|
||||
|
||||
sec := Cfg.Section("attachment")
|
||||
storageType := sec.Key("STORAGE_TYPE").MustString("")
|
||||
storage := getStorage("attachments", storageType, sec)
|
||||
|
||||
assert.EqualValues(t, "minio", storage.Type)
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/migrations"
|
||||
migration "code.gitea.io/gitea/modules/migrations/base"
|
||||
"code.gitea.io/gitea/modules/notification"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
@@ -82,11 +84,6 @@ func runMigrateTask(t *models.Task) (err error) {
|
||||
if err = t.LoadOwner(); err != nil {
|
||||
return
|
||||
}
|
||||
t.StartTime = timeutil.TimeStampNow()
|
||||
t.Status = structs.TaskStatusRunning
|
||||
if err = t.UpdateCols("start_time", "status"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var opts *migration.MigrateOptions
|
||||
opts, err = t.MigrateConfig()
|
||||
@@ -96,7 +93,20 @@ func runMigrateTask(t *models.Task) (err error) {
|
||||
|
||||
opts.MigrateToRepoID = t.RepoID
|
||||
var repo *models.Repository
|
||||
repo, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), t.Doer, t.Owner.Name, *opts)
|
||||
|
||||
ctx, cancel := context.WithCancel(graceful.GetManager().ShutdownContext())
|
||||
defer cancel()
|
||||
pm := process.GetManager()
|
||||
pid := pm.Add(fmt.Sprintf("MigrateTask: %s/%s", t.Owner.Name, opts.RepoName), cancel)
|
||||
defer pm.Remove(pid)
|
||||
|
||||
t.StartTime = timeutil.TimeStampNow()
|
||||
t.Status = structs.TaskStatusRunning
|
||||
if err = t.UpdateCols("start_time", "status"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
repo, err = migrations.MigrateRepository(ctx, t.Doer, t.Owner.Name, *opts)
|
||||
if err == nil {
|
||||
log.Trace("Repository migrated [%d]: %s/%s", repo.ID, t.Owner.Name, repo.Name)
|
||||
return
|
||||
|
||||
@@ -17,11 +17,24 @@ import (
|
||||
type (
|
||||
// FeishuPayload represents
|
||||
FeishuPayload struct {
|
||||
Title string `json:"title"`
|
||||
Text string `json:"text"`
|
||||
MsgType string `json:"msg_type"` // text / post / image / share_chat / interactive
|
||||
Content struct {
|
||||
Text string `json:"text"`
|
||||
} `json:"content"`
|
||||
}
|
||||
)
|
||||
|
||||
func newFeishuTextPayload(text string) *FeishuPayload {
|
||||
return &FeishuPayload{
|
||||
MsgType: "text",
|
||||
Content: struct {
|
||||
Text string `json:"text"`
|
||||
}{
|
||||
Text: text,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SetSecret sets the Feishu secret
|
||||
func (f *FeishuPayload) SetSecret(_ string) {}
|
||||
|
||||
@@ -42,34 +55,25 @@ var (
|
||||
func (f *FeishuPayload) Create(p *api.CreatePayload) (api.Payloader, error) {
|
||||
// created tag/branch
|
||||
refName := git.RefEndName(p.Ref)
|
||||
title := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName)
|
||||
text := fmt.Sprintf("[%s] %s %s created", p.Repo.FullName, p.RefType, refName)
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: title,
|
||||
Title: title,
|
||||
}, nil
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
// Delete implements PayloadConvertor Delete method
|
||||
func (f *FeishuPayload) Delete(p *api.DeletePayload) (api.Payloader, error) {
|
||||
// created tag/branch
|
||||
refName := git.RefEndName(p.Ref)
|
||||
title := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName)
|
||||
text := fmt.Sprintf("[%s] %s %s deleted", p.Repo.FullName, p.RefType, refName)
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: title,
|
||||
Title: title,
|
||||
}, nil
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
// Fork implements PayloadConvertor Fork method
|
||||
func (f *FeishuPayload) Fork(p *api.ForkPayload) (api.Payloader, error) {
|
||||
title := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName)
|
||||
text := fmt.Sprintf("%s is forked to %s", p.Forkee.FullName, p.Repo.FullName)
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: title,
|
||||
Title: title,
|
||||
}, nil
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
// Push implements PayloadConvertor Push method
|
||||
@@ -79,9 +83,7 @@ func (f *FeishuPayload) Push(p *api.PushPayload) (api.Payloader, error) {
|
||||
commitDesc string
|
||||
)
|
||||
|
||||
title := fmt.Sprintf("[%s:%s] %s", p.Repo.FullName, branchName, commitDesc)
|
||||
|
||||
var text string
|
||||
var text = fmt.Sprintf("[%s:%s] %s\n", p.Repo.FullName, branchName, commitDesc)
|
||||
// for each commit, generate attachment text
|
||||
for i, commit := range p.Commits {
|
||||
var authorName string
|
||||
@@ -96,40 +98,28 @@ func (f *FeishuPayload) Push(p *api.PushPayload) (api.Payloader, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: text,
|
||||
Title: title,
|
||||
}, nil
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
// Issue implements PayloadConvertor Issue method
|
||||
func (f *FeishuPayload) Issue(p *api.IssuePayload) (api.Payloader, error) {
|
||||
text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: text + "\r\n\r\n" + attachmentText,
|
||||
Title: issueTitle,
|
||||
}, nil
|
||||
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
|
||||
}
|
||||
|
||||
// IssueComment implements PayloadConvertor IssueComment method
|
||||
func (f *FeishuPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) {
|
||||
text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true)
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: text + "\r\n\r\n" + p.Comment.Body,
|
||||
Title: issueTitle,
|
||||
}, nil
|
||||
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + p.Comment.Body), nil
|
||||
}
|
||||
|
||||
// PullRequest implements PayloadConvertor PullRequest method
|
||||
func (f *FeishuPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) {
|
||||
text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: text + "\r\n\r\n" + attachmentText,
|
||||
Title: issueTitle,
|
||||
}, nil
|
||||
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
|
||||
}
|
||||
|
||||
// Review implements PayloadConvertor Review method
|
||||
@@ -147,28 +137,19 @@ func (f *FeishuPayload) Review(p *api.PullRequestPayload, event models.HookEvent
|
||||
|
||||
}
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: title + "\r\n\r\n" + text,
|
||||
Title: title,
|
||||
}, nil
|
||||
return newFeishuTextPayload(title + "\r\n\r\n" + text), nil
|
||||
}
|
||||
|
||||
// Repository implements PayloadConvertor Repository method
|
||||
func (f *FeishuPayload) Repository(p *api.RepositoryPayload) (api.Payloader, error) {
|
||||
var title string
|
||||
var text string
|
||||
switch p.Action {
|
||||
case api.HookRepoCreated:
|
||||
title = fmt.Sprintf("[%s] Repository created", p.Repository.FullName)
|
||||
return &FeishuPayload{
|
||||
Text: title,
|
||||
Title: title,
|
||||
}, nil
|
||||
text = fmt.Sprintf("[%s] Repository created", p.Repository.FullName)
|
||||
return newFeishuTextPayload(text), nil
|
||||
case api.HookRepoDeleted:
|
||||
title = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName)
|
||||
return &FeishuPayload{
|
||||
Title: title,
|
||||
Text: title,
|
||||
}, nil
|
||||
text = fmt.Sprintf("[%s] Repository deleted", p.Repository.FullName)
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
@@ -178,10 +159,7 @@ func (f *FeishuPayload) Repository(p *api.RepositoryPayload) (api.Payloader, err
|
||||
func (f *FeishuPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
|
||||
text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true)
|
||||
|
||||
return &FeishuPayload{
|
||||
Text: text,
|
||||
Title: text,
|
||||
}, nil
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
// GetFeishuPayload converts a ding talk webhook into a FeishuPayload
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
@@ -71,6 +73,8 @@ func UnadoptedRepos(ctx *context.Context) {
|
||||
opts.Page = 1
|
||||
}
|
||||
|
||||
ctx.Data["CurrentPage"] = opts.Page
|
||||
|
||||
doSearch := ctx.QueryBool("search")
|
||||
|
||||
ctx.Data["search"] = doSearch
|
||||
@@ -79,6 +83,7 @@ func UnadoptedRepos(ctx *context.Context) {
|
||||
if !doSearch {
|
||||
pager := context.NewPagination(0, opts.PageSize, opts.Page, 5)
|
||||
pager.SetDefaultParams(ctx)
|
||||
pager.AddParam(ctx, "search", "search")
|
||||
ctx.Data["Page"] = pager
|
||||
ctx.HTML(200, tplUnadoptedRepos)
|
||||
return
|
||||
@@ -92,6 +97,7 @@ func UnadoptedRepos(ctx *context.Context) {
|
||||
ctx.Data["Dirs"] = repoNames
|
||||
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
|
||||
pager.SetDefaultParams(ctx)
|
||||
pager.AddParam(ctx, "search", "search")
|
||||
ctx.Data["Page"] = pager
|
||||
ctx.HTML(200, tplUnadoptedRepos)
|
||||
}
|
||||
@@ -100,6 +106,9 @@ func UnadoptedRepos(ctx *context.Context) {
|
||||
func AdoptOrDeleteRepository(ctx *context.Context) {
|
||||
dir := ctx.Query("id")
|
||||
action := ctx.Query("action")
|
||||
page := ctx.QueryInt("page")
|
||||
q := ctx.Query("q")
|
||||
|
||||
dirSplit := strings.SplitN(dir, "/", 2)
|
||||
if len(dirSplit) != 2 {
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/repos")
|
||||
@@ -141,5 +150,5 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
||||
}
|
||||
ctx.Flash.Success(ctx.Tr("repo.delete_preexisting_success", dir))
|
||||
}
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/repos/unadopted")
|
||||
ctx.Redirect(setting.AppSubURL + "/admin/repos/unadopted?search=true&q=" + url.QueryEscape(q) + "&page=" + strconv.Itoa(page))
|
||||
}
|
||||
|
||||
@@ -17,19 +17,28 @@ import (
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
)
|
||||
|
||||
func listUserOrgs(ctx *context.APIContext, u *models.User, all bool) {
|
||||
if err := u.GetOrganizations(&models.SearchOrganizationsOptions{
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
All: all,
|
||||
}); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetOrganizations", err)
|
||||
func listUserOrgs(ctx *context.APIContext, u *models.User) {
|
||||
|
||||
listOptions := utils.GetListOptions(ctx)
|
||||
showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == u.ID)
|
||||
|
||||
orgs, err := models.GetOrgsByUserID(u.ID, showPrivate)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetOrgsByUserID", err)
|
||||
return
|
||||
}
|
||||
maxResults := len(orgs)
|
||||
|
||||
apiOrgs := make([]*api.Organization, len(u.Orgs))
|
||||
for i := range u.Orgs {
|
||||
apiOrgs[i] = convert.ToOrganization(u.Orgs[i])
|
||||
orgs = utils.PaginateUserSlice(orgs, listOptions.Page, listOptions.PageSize)
|
||||
|
||||
apiOrgs := make([]*api.Organization, len(orgs))
|
||||
for i := range orgs {
|
||||
apiOrgs[i] = convert.ToOrganization(orgs[i])
|
||||
}
|
||||
|
||||
ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
|
||||
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
|
||||
ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
|
||||
ctx.JSON(http.StatusOK, &apiOrgs)
|
||||
}
|
||||
|
||||
@@ -53,7 +62,7 @@ func ListMyOrgs(ctx *context.APIContext) {
|
||||
// "200":
|
||||
// "$ref": "#/responses/OrganizationList"
|
||||
|
||||
listUserOrgs(ctx, ctx.User, true)
|
||||
listUserOrgs(ctx, ctx.User)
|
||||
}
|
||||
|
||||
// ListUserOrgs list user's orgs
|
||||
@@ -85,7 +94,7 @@ func ListUserOrgs(ctx *context.APIContext) {
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
listUserOrgs(ctx, u, ctx.User != nil && (ctx.User.IsAdmin || ctx.User.ID == u.ID))
|
||||
listUserOrgs(ctx, u)
|
||||
}
|
||||
|
||||
// GetAll return list of all public organizations
|
||||
|
||||
@@ -244,7 +244,7 @@ type combinedCommitStatus struct {
|
||||
|
||||
// GetCombinedCommitStatusByRef returns the combined status for any given commit hash
|
||||
func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/commits/{ref}/statuses repository repoGetCombinedStatusByRef
|
||||
// swagger:operation GET /repos/{owner}/{repo}/commits/{ref}/status repository repoGetCombinedStatusByRef
|
||||
// ---
|
||||
// summary: Get a commit's combined status, by branch/tag/commit reference
|
||||
// produces:
|
||||
@@ -272,7 +272,7 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
|
||||
// required: false
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/Status"
|
||||
// "$ref": "#/responses/CombinedStatus"
|
||||
// "400":
|
||||
// "$ref": "#/responses/error"
|
||||
|
||||
@@ -292,7 +292,7 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
if len(statuses) == 0 {
|
||||
ctx.Status(http.StatusOK)
|
||||
ctx.JSON(http.StatusOK, &api.CombinedStatus{})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -309,3 +309,10 @@ type swaggerLanguageStatistics struct {
|
||||
// in: body
|
||||
Body map[string]int64 `json:"body"`
|
||||
}
|
||||
|
||||
// CombinedStatus
|
||||
// swagger:response CombinedStatus
|
||||
type swaggerCombinedStatus struct {
|
||||
// in: body
|
||||
Body api.CombinedStatus `json:"body"`
|
||||
}
|
||||
|
||||
@@ -66,3 +66,22 @@ func GetListOptions(ctx *context.APIContext) models.ListOptions {
|
||||
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
|
||||
}
|
||||
}
|
||||
|
||||
// PaginateUserSlice cut a slice of Users as per pagination options
|
||||
// TODO: make it generic
|
||||
func PaginateUserSlice(items []*models.User, page, pageSize int) []*models.User {
|
||||
if page != 0 {
|
||||
page--
|
||||
}
|
||||
|
||||
if page*pageSize >= len(items) {
|
||||
return items[len(items):]
|
||||
}
|
||||
|
||||
items = items[page*pageSize:]
|
||||
|
||||
if len(items) > pageSize {
|
||||
return items[:pageSize]
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
@@ -223,10 +223,11 @@ func NewMacaron() *macaron.Macaron {
|
||||
},
|
||||
))
|
||||
|
||||
m.Use(templates.HTMLRenderer())
|
||||
|
||||
m.Use(storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars))
|
||||
m.Use(storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars))
|
||||
|
||||
m.Use(templates.HTMLRenderer())
|
||||
mailer.InitMailRender(templates.Mailer())
|
||||
|
||||
localeNames, err := options.Dir("locale")
|
||||
|
||||
@@ -174,12 +174,12 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) {
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplSignIn, &form)
|
||||
log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
} else if models.IsErrEmailAlreadyUsed(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSignIn, &form)
|
||||
log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
} else if models.IsErrUserProhibitLogin(err) {
|
||||
log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(200, "user/auth/prohibit_login")
|
||||
} else if models.IsErrUserInactive(err) {
|
||||
@@ -187,7 +187,7 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
|
||||
ctx.HTML(200, TplActivate)
|
||||
} else {
|
||||
log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(200, "user/auth/prohibit_login")
|
||||
}
|
||||
@@ -570,8 +570,17 @@ func SignInOAuth(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
err = oauth2.Auth(loginSource.Name, ctx.Req.Request, ctx.Resp)
|
||||
if err != nil {
|
||||
if err = oauth2.Auth(loginSource.Name, ctx.Req.Request, ctx.Resp); err != nil {
|
||||
if strings.Contains(err.Error(), "no provider for ") {
|
||||
if err = models.ResetOAuth2(); err != nil {
|
||||
ctx.ServerError("SignIn", err)
|
||||
return
|
||||
}
|
||||
if err = oauth2.Auth(loginSource.Name, ctx.Req.Request, ctx.Resp); err != nil {
|
||||
ctx.ServerError("SignIn", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.ServerError("SignIn", err)
|
||||
}
|
||||
// redirect is done in oauth2.Auth
|
||||
@@ -1496,7 +1505,7 @@ func ResetPasswdPost(ctx *context.Context) {
|
||||
}
|
||||
u.HashPassword(passwd)
|
||||
u.MustChangePassword = false
|
||||
if err := models.UpdateUserCols(u, "must_change_password", "passwd", "rands", "salt"); err != nil {
|
||||
if err := models.UpdateUserCols(u, "must_change_password", "passwd", "passwd_hash_algo", "rands", "salt"); err != nil {
|
||||
ctx.ServerError("UpdateUser", err)
|
||||
return
|
||||
}
|
||||
@@ -1572,7 +1581,7 @@ func MustChangePasswordPost(ctx *context.Context, cpt *captcha.Captcha, form aut
|
||||
u.HashPassword(form.Password)
|
||||
u.MustChangePassword = false
|
||||
|
||||
if err := models.UpdateUserCols(u, "must_change_password", "passwd", "salt"); err != nil {
|
||||
if err := models.UpdateUserCols(u, "must_change_password", "passwd", "passwd_hash_algo", "salt"); err != nil {
|
||||
ctx.ServerError("UpdateUser", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func AccountPost(ctx *context.Context, form auth.ChangePasswordForm) {
|
||||
return
|
||||
}
|
||||
ctx.User.HashPassword(form.Password)
|
||||
if err := models.UpdateUserCols(ctx.User, "salt", "passwd"); err != nil {
|
||||
if err := models.UpdateUserCols(ctx.User, "salt", "passwd_hash_algo", "passwd"); err != nil {
|
||||
ctx.ServerError("UpdateUser", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -164,9 +165,9 @@ func getDiffLineSectionInfo(treePath, line string, lastLeftIdx, lastRightIdx int
|
||||
// escape a line's content or return <br> needed for copy/paste purposes
|
||||
func getLineContent(content string) string {
|
||||
if len(content) > 0 {
|
||||
return content
|
||||
return html.EscapeString(content)
|
||||
}
|
||||
return "\n"
|
||||
return "<br>"
|
||||
}
|
||||
|
||||
// DiffSection represents a section of a DiffFile.
|
||||
@@ -357,8 +358,6 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) tem
|
||||
diffRecord := diffMatchPatch.DiffMain(highlight.Code(diffSection.FileName, diff1[1:]), highlight.Code(diffSection.FileName, diff2[1:]), true)
|
||||
diffRecord = diffMatchPatch.DiffCleanupEfficiency(diffRecord)
|
||||
|
||||
diffRecord = diffMatchPatch.DiffCleanupEfficiency(diffRecord)
|
||||
|
||||
return diffToHTML(diffSection.FileName, diffRecord, diffLine.Type)
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,17 @@ func mailIssueCommentBatch(ctx *mailCommentContext, ids []int64, visited map[int
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Check issue visibility for each user
|
||||
|
||||
// Make sure all recipients can still see the issue
|
||||
idx := 0
|
||||
for _, r := range recipients {
|
||||
if ctx.Issue.Repo.CheckUnitUser(r, models.UnitTypeIssues) {
|
||||
recipients[idx] = r
|
||||
idx++
|
||||
}
|
||||
}
|
||||
recipients = recipients[:idx]
|
||||
|
||||
// TODO: Separate recipients by language for i18n mail templates
|
||||
tos := make([]string, len(recipients))
|
||||
for i := range recipients {
|
||||
|
||||
@@ -149,6 +149,11 @@ func parseRemoteUpdateOutput(output string) []*mirrorSyncResult {
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(lines[i], " * "): // New reference
|
||||
if strings.HasPrefix(lines[i], " * [new tag]") {
|
||||
refName = git.TagPrefix + refName
|
||||
} else if strings.HasPrefix(lines[i], " * [new branch]") {
|
||||
refName = git.BranchPrefix + refName
|
||||
}
|
||||
results = append(results, &mirrorSyncResult{
|
||||
refName: refName,
|
||||
oldCommitID: gitShortEmptySha,
|
||||
@@ -434,6 +439,17 @@ func syncMirror(repoID string) {
|
||||
|
||||
// Create reference
|
||||
if result.oldCommitID == gitShortEmptySha {
|
||||
if tp == git.TagPrefix {
|
||||
tp = "tag"
|
||||
} else if tp == git.BranchPrefix {
|
||||
tp = "branch"
|
||||
}
|
||||
commitID, err := gitRepo.GetRefCommitID(result.refName)
|
||||
if err != nil {
|
||||
log.Error("gitRepo.GetRefCommitID [repo_id: %s, ref_name: %s]: %v", m.RepoID, result.refName, err)
|
||||
continue
|
||||
}
|
||||
notification.NotifySyncPushCommits(m.Repo.MustOwner(), m.Repo, result.refName, git.EmptySHA, commitID, repo_module.NewPushCommits())
|
||||
notification.NotifySyncCreateRef(m.Repo.MustOwner(), m.Repo, tp, result.refName)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package mirror
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
@@ -47,7 +48,7 @@ func TestRelease_MirrorDelete(t *testing.T) {
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
mirror, err := repository.MigrateRepositoryGitData(user, user, mirrorRepo, opts)
|
||||
mirror, err := repository.MigrateRepositoryGitData(context.Background(), user, mirrorRepo, opts)
|
||||
assert.NoError(t, err)
|
||||
|
||||
gitRepo, err := git.OpenRepository(repoPath)
|
||||
|
||||
@@ -411,7 +411,7 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge
|
||||
)
|
||||
|
||||
// Push back to upstream.
|
||||
if err := git.NewCommand("push", "origin", baseBranch+":"+pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
|
||||
if err := git.NewCommand("push", "origin", baseBranch+":refs/heads/"+pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil {
|
||||
if strings.Contains(errbuf.String(), "non-fast-forward") {
|
||||
return "", &git.ErrPushOutOfDate{
|
||||
StdOut: outbuf.String(),
|
||||
|
||||
@@ -167,16 +167,16 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models
|
||||
|
||||
// Only fetch diff if comment is review comment
|
||||
if len(patch) == 0 && reviewID != 0 {
|
||||
if len(commitID) == 0 {
|
||||
commitID, err = gitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetRefCommitID[%s]: %v", pr.GetGitRefName(), err)
|
||||
}
|
||||
headCommitID, err := gitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetRefCommitID[%s]: %v", pr.GetGitRefName(), err)
|
||||
}
|
||||
if len(commitID) == 0 {
|
||||
commitID = headCommitID
|
||||
}
|
||||
|
||||
patchBuf := new(bytes.Buffer)
|
||||
if err := git.GetRepoRawDiffForFile(gitRepo, pr.MergeBase, commitID, git.RawDiffNormal, treePath, patchBuf); err != nil {
|
||||
return nil, fmt.Errorf("GetRawDiffForLine[%s, %s, %s, %s]: %v", gitRepo.Path, pr.MergeBase, commitID, treePath, err)
|
||||
if err := git.GetRepoRawDiffForFile(gitRepo, pr.MergeBase, headCommitID, git.RawDiffNormal, treePath, patchBuf); err != nil {
|
||||
return nil, fmt.Errorf("GetRawDiffForLine[%s, %s, %s, %s]: %v", gitRepo.Path, pr.MergeBase, headCommitID, treePath, err)
|
||||
}
|
||||
patch = git.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: line}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
|
||||
}
|
||||
|
||||
@@ -142,6 +142,10 @@ func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error {
|
||||
return fmt.Errorf("git tag -d: %v", err)
|
||||
}
|
||||
|
||||
notification.NotifyPushCommits(
|
||||
doer, repo, git.TagPrefix+rel.TagName, rel.Sha1, git.EmptySHA, repository.NewPushCommits())
|
||||
notification.NotifyDeleteRef(doer, repo, "tag", git.TagPrefix+rel.TagName)
|
||||
|
||||
if err := models.DeleteReleaseByID(id); err != nil {
|
||||
return fmt.Errorf("DeleteReleaseByID: %v", err)
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ func InitWiki(repo *models.Repository) error {
|
||||
return fmt.Errorf("InitRepository: %v", err)
|
||||
} else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
|
||||
return fmt.Errorf("createDelegateHooks: %v", err)
|
||||
} else if _, err = git.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+"master").RunInDir(repo.WikiPath()); err != nil {
|
||||
return fmt.Errorf("unable to set default wiki branch to master: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
{{$.CsrfTokenHtml}}
|
||||
<input type="hidden" name="id" value="{{$dir}}">
|
||||
<input type="hidden" name="action" value="adopt">
|
||||
<input type="hidden" name="q" value="{{$.Keyword}}">
|
||||
<input type="hidden" name="page" value="{{$.CurrentPage}}">
|
||||
<div class="actions">
|
||||
<div class="ui red basic inverted cancel button">
|
||||
<i class="remove icon"></i>
|
||||
@@ -66,6 +68,8 @@
|
||||
{{$.CsrfTokenHtml}}
|
||||
<input type="hidden" name="id" value="{{$dir}}">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="q" value="{{$.Keyword}}">
|
||||
<input type="hidden" name="page" value="{{$.CurrentPage}}">
|
||||
<div class="actions">
|
||||
<div class="ui red basic inverted cancel button">
|
||||
<i class="remove icon"></i>
|
||||
|
||||
@@ -166,74 +166,78 @@
|
||||
<td class="lines-num"></td>
|
||||
<td class="lines-type-marker"></td>
|
||||
<td class="add-comment-left">
|
||||
{{if and $resolved (eq $line.GetCommentSide "previous")}}
|
||||
<div class="ui top attached header">
|
||||
<span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span>
|
||||
<button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated">
|
||||
{{svg "octicon-unfold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.show_resolved"}}
|
||||
</button>
|
||||
<button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated">
|
||||
{{svg "octicon-fold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.hide_resolved"}}
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $line.GetCommentSide "previous"}}
|
||||
<div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}">
|
||||
<div class="comment-list">
|
||||
<ui class="ui comments">
|
||||
{{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}}
|
||||
</ui>
|
||||
</div>
|
||||
{{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.Comments 0)}}
|
||||
{{if and $.CanMarkConversation $isNotPending}}
|
||||
<button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $line.Comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" >
|
||||
{{if $resolved}}
|
||||
{{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}}
|
||||
{{else}}
|
||||
{{$.i18n.Tr "repo.issues.review.resolve_conversation"}}
|
||||
{{end}}
|
||||
<div class="conversation-holder">
|
||||
{{if and $resolved (eq $line.GetCommentSide "previous")}}
|
||||
<div class="ui top attached header">
|
||||
<span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span>
|
||||
<button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated">
|
||||
{{svg "octicon-unfold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.show_resolved"}}
|
||||
</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated">
|
||||
{{svg "octicon-fold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.hide_resolved"}}
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $line.GetCommentSide "previous"}}
|
||||
<div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}">
|
||||
<div class="comment-list">
|
||||
<ui class="ui comments">
|
||||
{{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}}
|
||||
</ui>
|
||||
</div>
|
||||
{{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.Comments 0)}}
|
||||
{{if and $.CanMarkConversation $isNotPending}}
|
||||
<button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $line.Comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" >
|
||||
{{if $resolved}}
|
||||
{{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}}
|
||||
{{else}}
|
||||
{{$.i18n.Tr "repo.issues.review.resolve_conversation"}}
|
||||
{{end}}
|
||||
</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</td>
|
||||
<td class="lines-num"></td>
|
||||
<td class="lines-type-marker"></td>
|
||||
<td class="add-comment-right">
|
||||
{{if and $resolved (eq $line.GetCommentSide "proposed")}}
|
||||
<div class="ui top attached header">
|
||||
<span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span>
|
||||
<button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated">
|
||||
{{svg "octicon-unfold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.show_resolved"}}
|
||||
</button>
|
||||
<button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated">
|
||||
{{svg "octicon-fold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.hide_resolved"}}
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $line.GetCommentSide "proposed"}}
|
||||
<div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}">
|
||||
<div class="comment-list">
|
||||
<ui class="ui comments">
|
||||
{{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}}
|
||||
</ui>
|
||||
</div>
|
||||
{{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.Comments 0)}}
|
||||
{{if and $.CanMarkConversation $isNotPending}}
|
||||
<button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $line.Comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" >
|
||||
{{if $resolved}}
|
||||
{{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}}
|
||||
{{else}}
|
||||
{{$.i18n.Tr "repo.issues.review.resolve_conversation"}}
|
||||
{{end}}
|
||||
<div class="conversation-holder">
|
||||
{{if and $resolved (eq $line.GetCommentSide "proposed")}}
|
||||
<div class="ui top attached header">
|
||||
<span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.i18n.Tr "repo.issues.review.resolved_by"}}</span>
|
||||
<button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated">
|
||||
{{svg "octicon-unfold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.show_resolved"}}
|
||||
</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated">
|
||||
{{svg "octicon-fold"}}
|
||||
{{$.i18n.Tr "repo.issues.review.hide_resolved"}}
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if eq $line.GetCommentSide "proposed"}}
|
||||
<div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}">
|
||||
<div class="comment-list">
|
||||
<ui class="ui comments">
|
||||
{{ template "repo/diff/comments" dict "root" $ "comments" $line.Comments}}
|
||||
</ui>
|
||||
</div>
|
||||
{{template "repo/diff/comment_form_datahandler" dict "reply" (index $line.Comments 0).ReviewID "hidden" true "root" $ "comment" (index $line.Comments 0)}}
|
||||
{{if and $.CanMarkConversation $isNotPending}}
|
||||
<button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $line.Comments 0).ID}}" data-update-url="{{$.RepoLink}}/issues/resolve_conversation" >
|
||||
{{if $resolved}}
|
||||
{{$.i18n.Tr "repo.issues.review.un_resolve_conversation"}}
|
||||
{{else}}
|
||||
{{$.i18n.Tr "repo.issues.review.resolve_conversation"}}
|
||||
{{end}}
|
||||
</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
@@ -39,35 +39,37 @@
|
||||
<tr>
|
||||
<td colspan="2" class="lines-num"></td>
|
||||
<td class="add-comment-left add-comment-right" colspan="2">
|
||||
{{if $resolved}}
|
||||
<div class = "ui attached header">
|
||||
<span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.root.i18n.Tr "repo.issues.review.resolved_by"}}</span>
|
||||
<button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated">
|
||||
{{svg "octicon-unfold"}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.show_resolved"}}
|
||||
</button>
|
||||
<button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated">
|
||||
{{svg "octicon-fold"}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.hide_resolved"}}
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
<div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}">
|
||||
<div class="comment-list">
|
||||
<ui class="ui comments">
|
||||
{{ template "repo/diff/comments" dict "root" $.root "comments" $line.Comments}}
|
||||
</ui>
|
||||
</div>
|
||||
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $line.Comments 0).ReviewID "root" $.root "comment" (index $line.Comments 0)}}
|
||||
{{if and $.root.CanMarkConversation $isNotPending}}
|
||||
<button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $line.Comments 0).ID}}" data-update-url="{{$.root.RepoLink}}/issues/resolve_conversation" >
|
||||
{{if $resolved}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.un_resolve_conversation"}}
|
||||
{{else}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.resolve_conversation"}}
|
||||
{{end}}
|
||||
</button>
|
||||
<div class="conversation-holder">
|
||||
{{if $resolved}}
|
||||
<div class = "ui attached header">
|
||||
<span class="ui grey text left"><b>{{$resolveDoer.Name}}</b> {{$.root.i18n.Tr "repo.issues.review.resolved_by"}}</span>
|
||||
<button id="show-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="ui compact right labeled button show-outdated">
|
||||
{{svg "octicon-unfold"}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.show_resolved"}}
|
||||
</button>
|
||||
<button id="hide-outdated-{{(index $line.Comments 0).ID}}" data-comment="{{(index $line.Comments 0).ID}}" class="hide ui compact right labeled button hide-outdated">
|
||||
{{svg "octicon-fold"}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.hide_resolved"}}
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
<div id="code-comments-{{(index $line.Comments 0).ID}}" class="field comment-code-cloud {{if $resolved}}hide{{end}}">
|
||||
<div class="comment-list">
|
||||
<ui class="ui comments">
|
||||
{{ template "repo/diff/comments" dict "root" $.root "comments" $line.Comments}}
|
||||
</ui>
|
||||
</div>
|
||||
{{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $line.Comments 0).ReviewID "root" $.root "comment" (index $line.Comments 0)}}
|
||||
{{if and $.root.CanMarkConversation $isNotPending}}
|
||||
<button class="ui icon tiny button resolve-conversation" data-action="{{if not $resolved}}Resolve{{else}}UnResolve{{end}}" data-comment-id="{{(index $line.Comments 0).ID}}" data-update-url="{{$.root.RepoLink}}/issues/resolve_conversation" >
|
||||
{{if $resolved}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.un_resolve_conversation"}}
|
||||
{{else}}
|
||||
{{$.root.i18n.Tr "repo.issues.review.resolve_conversation"}}
|
||||
{{end}}
|
||||
</button>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
</div>
|
||||
<div class="extra content">
|
||||
{{ range .Labels }}
|
||||
<a class="ui label has-emoji" href="{{$.RepoLink}}/issues?labels={{.ID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}; margin-bottom: 3px;" title="{{.Description}}">{{.Name}}</a>
|
||||
<a class="ui label" href="{{$.RepoLink}}/issues?labels={{.ID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}; margin-bottom: 3px;" title="{{.Description | RenderEmojiPlain}}">{{.Name | RenderEmoji}}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2829,7 +2829,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/commits/{ref}/statuses": {
|
||||
"/repos/{owner}/{repo}/commits/{ref}/status": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@@ -2870,7 +2870,88 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/Status"
|
||||
"$ref": "#/responses/CombinedStatus"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/responses/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/commits/{ref}/statuses": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"repository"
|
||||
],
|
||||
"summary": "Get a commit's statuses, by branch/tag/commit reference",
|
||||
"operationId": "repoListStatusesByRef",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of branch/tag/commit",
|
||||
"name": "ref",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"oldest",
|
||||
"recentupdate",
|
||||
"leastupdate",
|
||||
"leastindex",
|
||||
"highestindex"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "type of sort",
|
||||
"name": "sort",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"pending",
|
||||
"success",
|
||||
"error",
|
||||
"failure",
|
||||
"warning"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "type of state",
|
||||
"name": "state",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page number of results to return (1-based)",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page size of results",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/StatusList"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/responses/error"
|
||||
@@ -11240,6 +11321,43 @@
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||
},
|
||||
"CombinedStatus": {
|
||||
"description": "CombinedStatus holds the combined state of several statuses for a single commit",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"commit_url": {
|
||||
"type": "string",
|
||||
"x-go-name": "CommitURL"
|
||||
},
|
||||
"repository": {
|
||||
"$ref": "#/definitions/Repository"
|
||||
},
|
||||
"sha": {
|
||||
"type": "string",
|
||||
"x-go-name": "SHA"
|
||||
},
|
||||
"state": {
|
||||
"$ref": "#/definitions/StatusState"
|
||||
},
|
||||
"statuses": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Status"
|
||||
},
|
||||
"x-go-name": "Statuses"
|
||||
},
|
||||
"total_count": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "TotalCount"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"x-go-name": "URL"
|
||||
}
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||
},
|
||||
"Comment": {
|
||||
"description": "Comment represents a comment on a commit or issue",
|
||||
"type": "object",
|
||||
@@ -15532,6 +15650,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"CombinedStatus": {
|
||||
"description": "CombinedStatus",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/CombinedStatus"
|
||||
}
|
||||
},
|
||||
"Comment": {
|
||||
"description": "Comment",
|
||||
"schema": {
|
||||
|
||||
97
vendor/github.com/microcosm-cc/bluemonday/sanitize.go
generated
vendored
97
vendor/github.com/microcosm-cc/bluemonday/sanitize.go
generated
vendored
@@ -122,22 +122,79 @@ func escapeUrlComponent(val string) string {
|
||||
return w.String()
|
||||
}
|
||||
|
||||
func sanitizedUrl(val string) (string, error) {
|
||||
// Query represents a query
|
||||
type Query struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
func parseQuery(query string) (values []Query, err error) {
|
||||
for query != "" {
|
||||
key := query
|
||||
if i := strings.IndexAny(key, "&;"); i >= 0 {
|
||||
key, query = key[:i], key[i+1:]
|
||||
} else {
|
||||
query = ""
|
||||
}
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
value := ""
|
||||
if i := strings.Index(key, "="); i >= 0 {
|
||||
key, value = key[:i], key[i+1:]
|
||||
}
|
||||
key, err1 := url.QueryUnescape(key)
|
||||
if err1 != nil {
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
continue
|
||||
}
|
||||
value, err1 = url.QueryUnescape(value)
|
||||
if err1 != nil {
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
continue
|
||||
}
|
||||
values = append(values, Query{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return values, err
|
||||
}
|
||||
|
||||
func encodeQueries(queries []Query) string {
|
||||
var b strings.Builder
|
||||
for i, query := range queries {
|
||||
b.WriteString(url.QueryEscape(query.Key))
|
||||
b.WriteString("=")
|
||||
b.WriteString(url.QueryEscape(query.Value))
|
||||
if i < len(queries)-1 {
|
||||
b.WriteString("&")
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func sanitizedURL(val string) (string, error) {
|
||||
u, err := url.Parse(val)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// sanitize the url query params
|
||||
sanitizedQueryValues := make(url.Values, 0)
|
||||
queryValues := u.Query()
|
||||
for k, vals := range queryValues {
|
||||
sk := html.EscapeString(k)
|
||||
for _, v := range vals {
|
||||
sv := escapeUrlComponent(v)
|
||||
sanitizedQueryValues.Set(sk, sv)
|
||||
}
|
||||
|
||||
// we use parseQuery but not u.Query to keep the order not change because
|
||||
// url.Values is a map which has a random order.
|
||||
queryValues, err := parseQuery(u.RawQuery)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
u.RawQuery = sanitizedQueryValues.Encode()
|
||||
// sanitize the url query params
|
||||
for i, query := range queryValues {
|
||||
queryValues[i].Key = html.EscapeString(query.Key)
|
||||
}
|
||||
u.RawQuery = encodeQueries(queryValues)
|
||||
// u.String() will also sanitize host/scheme/user/pass
|
||||
return u.String(), nil
|
||||
}
|
||||
@@ -158,7 +215,7 @@ func (p *Policy) writeLinkableBuf(buff *bytes.Buffer, token *html.Token) {
|
||||
tokenBuff.WriteString(html.EscapeString(attr.Val))
|
||||
continue
|
||||
}
|
||||
u, err := sanitizedUrl(u)
|
||||
u, err := sanitizedURL(u)
|
||||
if err == nil {
|
||||
tokenBuff.WriteString(u)
|
||||
} else {
|
||||
@@ -390,10 +447,10 @@ func (p *Policy) sanitizeAttrs(
|
||||
hasStylePolicies = true
|
||||
}
|
||||
// no specific element policy found, look for a pattern match
|
||||
if !hasStylePolicies{
|
||||
for k, v := range p.elsMatchingAndStyles{
|
||||
if !hasStylePolicies {
|
||||
for k, v := range p.elsMatchingAndStyles {
|
||||
if k.MatchString(elementName) {
|
||||
if len(v) > 0{
|
||||
if len(v) > 0 {
|
||||
hasStylePolicies = true
|
||||
break
|
||||
}
|
||||
@@ -669,14 +726,14 @@ func (p *Policy) sanitizeAttrs(
|
||||
|
||||
func (p *Policy) sanitizeStyles(attr html.Attribute, elementName string) html.Attribute {
|
||||
sps := p.elsAndStyles[elementName]
|
||||
if len(sps) == 0{
|
||||
if len(sps) == 0 {
|
||||
sps = map[string]stylePolicy{}
|
||||
// check for any matching elements, if we don't already have a policy found
|
||||
// if multiple matches are found they will be overwritten, it's best
|
||||
// to not have overlapping matchers
|
||||
for regex, policies :=range p.elsMatchingAndStyles{
|
||||
if regex.MatchString(elementName){
|
||||
for k, v := range policies{
|
||||
for regex, policies := range p.elsMatchingAndStyles {
|
||||
if regex.MatchString(elementName) {
|
||||
for k, v := range policies {
|
||||
sps[k] = v
|
||||
}
|
||||
}
|
||||
@@ -874,7 +931,7 @@ func removeUnicode(value string) string {
|
||||
return substitutedValue
|
||||
}
|
||||
|
||||
func (p *Policy) matchRegex(elementName string ) (map[string]attrPolicy, bool) {
|
||||
func (p *Policy) matchRegex(elementName string) (map[string]attrPolicy, bool) {
|
||||
aps := make(map[string]attrPolicy, 0)
|
||||
matched := false
|
||||
for regex, attrs := range p.elsMatchingAndAttrs {
|
||||
|
||||
4
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
4
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
@@ -363,6 +363,10 @@ func AcceptTOS(tosURL string) bool { return true }
|
||||
// Also see Error's Instance field for when a CA requires already registered accounts to agree
|
||||
// to an updated Terms of Service.
|
||||
func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
|
||||
if c.Key == nil {
|
||||
return nil, errors.New("acme: client.Key must be set to Register")
|
||||
}
|
||||
|
||||
dir, err := c.Discover(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
69
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
69
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
@@ -7,17 +7,31 @@ package acme
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
_ "crypto/sha512" // need for EC keys
|
||||
"encoding/asn1"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// MACAlgorithm represents a JWS MAC signature algorithm.
|
||||
// See https://tools.ietf.org/html/rfc7518#section-3.1 for more details.
|
||||
type MACAlgorithm string
|
||||
|
||||
const (
|
||||
MACAlgorithmHS256 = MACAlgorithm("HS256")
|
||||
MACAlgorithmHS384 = MACAlgorithm("HS384")
|
||||
MACAlgorithmHS512 = MACAlgorithm("HS512")
|
||||
)
|
||||
|
||||
// keyID is the account identity provided by a CA during registration.
|
||||
type keyID string
|
||||
|
||||
@@ -31,6 +45,14 @@ const noKeyID = keyID("")
|
||||
// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details.
|
||||
const noPayload = ""
|
||||
|
||||
// jsonWebSignature can be easily serialized into a JWS following
|
||||
// https://tools.ietf.org/html/rfc7515#section-3.2.
|
||||
type jsonWebSignature struct {
|
||||
Protected string `json:"protected"`
|
||||
Payload string `json:"payload"`
|
||||
Sig string `json:"signature"`
|
||||
}
|
||||
|
||||
// jwsEncodeJSON signs claimset using provided key and a nonce.
|
||||
// The result is serialized in JSON format containing either kid or jwk
|
||||
// fields based on the provided keyID value.
|
||||
@@ -71,12 +93,7 @@ func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid keyID, nonce, ur
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
enc := struct {
|
||||
Protected string `json:"protected"`
|
||||
Payload string `json:"payload"`
|
||||
Sig string `json:"signature"`
|
||||
}{
|
||||
enc := jsonWebSignature{
|
||||
Protected: phead,
|
||||
Payload: payload,
|
||||
Sig: base64.RawURLEncoding.EncodeToString(sig),
|
||||
@@ -84,6 +101,32 @@ func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid keyID, nonce, ur
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// jwsWithMAC creates and signs a JWS using the given key and algorithm.
|
||||
// "rawProtected" and "rawPayload" should not be base64-URL-encoded.
|
||||
func jwsWithMAC(key []byte, alg MACAlgorithm, rawProtected, rawPayload []byte) (*jsonWebSignature, error) {
|
||||
if len(key) == 0 {
|
||||
return nil, errors.New("acme: cannot sign JWS with an empty MAC key")
|
||||
}
|
||||
protected := base64.RawURLEncoding.EncodeToString(rawProtected)
|
||||
payload := base64.RawURLEncoding.EncodeToString(rawPayload)
|
||||
|
||||
// Only HMACs are currently supported.
|
||||
hmac, err := newHMAC(key, alg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := hmac.Write([]byte(protected + "." + payload)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mac := hmac.Sum(nil)
|
||||
|
||||
return &jsonWebSignature{
|
||||
Protected: protected,
|
||||
Payload: payload,
|
||||
Sig: base64.RawURLEncoding.EncodeToString(mac),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// jwkEncode encodes public part of an RSA or ECDSA key into a JWK.
|
||||
// The result is also suitable for creating a JWK thumbprint.
|
||||
// https://tools.ietf.org/html/rfc7517
|
||||
@@ -175,6 +218,20 @@ func jwsHasher(pub crypto.PublicKey) (string, crypto.Hash) {
|
||||
return "", 0
|
||||
}
|
||||
|
||||
// newHMAC returns an appropriate HMAC for the given MACAlgorithm.
|
||||
func newHMAC(key []byte, alg MACAlgorithm) (hash.Hash, error) {
|
||||
switch alg {
|
||||
case MACAlgorithmHS256:
|
||||
return hmac.New(sha256.New, key), nil
|
||||
case MACAlgorithmHS384:
|
||||
return hmac.New(sha512.New384, key), nil
|
||||
case MACAlgorithmHS512:
|
||||
return hmac.New(sha512.New, key), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("acme: unsupported MAC algorithm: %v", alg)
|
||||
}
|
||||
}
|
||||
|
||||
// JWKThumbprint creates a JWK thumbprint out of pub
|
||||
// as specified in https://tools.ietf.org/html/rfc7638.
|
||||
func JWKThumbprint(pub crypto.PublicKey) (string, error) {
|
||||
|
||||
33
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
33
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
@@ -5,6 +5,7 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"encoding/base64"
|
||||
@@ -37,22 +38,32 @@ func (c *Client) DeactivateReg(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// registerRFC is quivalent to c.Register but for CAs implementing RFC 8555.
|
||||
// registerRFC is equivalent to c.Register but for CAs implementing RFC 8555.
|
||||
// It expects c.Discover to have already been called.
|
||||
// TODO: Implement externalAccountBinding.
|
||||
func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
|
||||
c.cacheMu.Lock() // guard c.kid access
|
||||
defer c.cacheMu.Unlock()
|
||||
|
||||
req := struct {
|
||||
TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"`
|
||||
Contact []string `json:"contact,omitempty"`
|
||||
TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"`
|
||||
Contact []string `json:"contact,omitempty"`
|
||||
ExternalAccountBinding *jsonWebSignature `json:"externalAccountBinding,omitempty"`
|
||||
}{
|
||||
Contact: acct.Contact,
|
||||
}
|
||||
if c.dir.Terms != "" {
|
||||
req.TermsAgreed = prompt(c.dir.Terms)
|
||||
}
|
||||
|
||||
// set 'externalAccountBinding' field if requested
|
||||
if acct.ExternalAccountBinding != nil {
|
||||
eabJWS, err := c.encodeExternalAccountBinding(acct.ExternalAccountBinding)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("acme: failed to encode external account binding: %v", err)
|
||||
}
|
||||
req.ExternalAccountBinding = eabJWS
|
||||
}
|
||||
|
||||
res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(
|
||||
http.StatusOK, // account with this key already registered
|
||||
http.StatusCreated, // new account created
|
||||
@@ -75,7 +86,19 @@ func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tos
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// updateGegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555.
|
||||
// encodeExternalAccountBinding will encode an external account binding stanza
|
||||
// as described in https://tools.ietf.org/html/rfc8555#section-7.3.4.
|
||||
func (c *Client) encodeExternalAccountBinding(eab *ExternalAccountBinding) (*jsonWebSignature, error) {
|
||||
jwk, err := jwkEncode(c.Key.Public())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var rProtected bytes.Buffer
|
||||
fmt.Fprintf(&rProtected, `{"alg":%q,"kid":%q,"url":%q}`, eab.Algorithm, eab.KID, c.dir.RegURL)
|
||||
return jwsWithMAC(eab.Key, eab.Algorithm, rProtected.Bytes(), []byte(jwk))
|
||||
}
|
||||
|
||||
// updateRegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555.
|
||||
// It expects c.Discover to have already been called.
|
||||
func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) {
|
||||
url := string(c.accountKID(ctx))
|
||||
|
||||
25
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
25
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
@@ -199,6 +199,31 @@ type Account struct {
|
||||
//
|
||||
// It is non-RFC 8555 compliant and is obsoleted by OrdersURL.
|
||||
Certificates string
|
||||
|
||||
// ExternalAccountBinding represents an arbitrary binding to an account of
|
||||
// the CA which the ACME server is tied to.
|
||||
// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details.
|
||||
ExternalAccountBinding *ExternalAccountBinding
|
||||
}
|
||||
|
||||
// ExternalAccountBinding contains the data needed to form a request with
|
||||
// an external account binding.
|
||||
// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details.
|
||||
type ExternalAccountBinding struct {
|
||||
// KID is the Key ID of the symmetric MAC key that the CA provides to
|
||||
// identify an external account from ACME.
|
||||
KID string
|
||||
|
||||
// Key is the bytes of the symmetric key that the CA provides to identify
|
||||
// the account. Key must correspond to the KID.
|
||||
Key []byte
|
||||
|
||||
// Algorithm used to sign the JWS.
|
||||
Algorithm MACAlgorithm
|
||||
}
|
||||
|
||||
func (e *ExternalAccountBinding) String() string {
|
||||
return fmt.Sprintf("&{KID: %q, Key: redacted, Algorithm: %v}", e.KID, e.Algorithm)
|
||||
}
|
||||
|
||||
// Directory is ACME server discovery data.
|
||||
|
||||
2
vendor/golang.org/x/crypto/argon2/blamka_amd64.go
generated
vendored
2
vendor/golang.org/x/crypto/argon2/blamka_amd64.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
package argon2
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/argon2/blamka_ref.go
generated
vendored
2
vendor/golang.org/x/crypto/argon2/blamka_ref.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !amd64 appengine gccgo
|
||||
// +build !amd64 purego !gc
|
||||
|
||||
package argon2
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
generated
vendored
2
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7,amd64,!gccgo,!appengine
|
||||
// +build go1.7,amd64,gc,!purego
|
||||
|
||||
package blake2b
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7,amd64,!gccgo,!appengine
|
||||
// +build go1.7,amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
generated
vendored
2
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.7,amd64,!gccgo,!appengine
|
||||
// +build !go1.7,amd64,gc,!purego
|
||||
|
||||
package blake2b
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/blake2b/blake2b_ref.go
generated
vendored
2
vendor/golang.org/x/crypto/blake2b/blake2b_ref.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !amd64 appengine gccgo
|
||||
// +build !amd64 purego !gc
|
||||
|
||||
package blake2b
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
generated
vendored
2
vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.11,!gccgo,!purego
|
||||
// +build go1.11,gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/chacha20/chacha_arm64.s
generated
vendored
2
vendor/golang.org/x/crypto/chacha20/chacha_arm64.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.11,!gccgo,!purego
|
||||
// +build go1.11,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
generated
vendored
2
vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo purego
|
||||
// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
generated
vendored
2
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
generated
vendored
2
vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
generated
vendored
@@ -19,7 +19,7 @@
|
||||
// The differences in this and the original implementation are
|
||||
// due to the calling conventions and initialization of constants.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
2
vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/chacha20/chacha_s390x.s
generated
vendored
2
vendor/golang.org/x/crypto/chacha20/chacha_s390x.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "textflag.h"
|
||||
|
||||
2
vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64,!gccgo,!appengine,!purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
package curve25519
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s
generated
vendored
@@ -5,7 +5,7 @@
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine,!purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#define REDMASK51 0x0007FFFFFFFFFFFF
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !amd64 gccgo appengine purego
|
||||
// +build !amd64 !gc purego
|
||||
|
||||
package curve25519
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/internal/subtle/aliasing.go
generated
vendored
2
vendor/golang.org/x/crypto/internal/subtle/aliasing.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !appengine
|
||||
// +build !purego
|
||||
|
||||
// Package subtle implements functions that are often useful in cryptographic
|
||||
// code but require careful thought to use correctly.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build appengine
|
||||
// +build purego
|
||||
|
||||
// Package subtle implements functions that are often useful in cryptographic
|
||||
// code but require careful thought to use correctly.
|
||||
2
vendor/golang.org/x/crypto/poly1305/mac_noasm.go
generated
vendored
2
vendor/golang.org/x/crypto/poly1305/mac_noasm.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !amd64,!ppc64le,!s390x gccgo purego
|
||||
// +build !amd64,!ppc64le,!s390x !gc purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/poly1305/sum_amd64.go
generated
vendored
2
vendor/golang.org/x/crypto/poly1305/sum_amd64.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go
generated
vendored
2
vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s
generated
vendored
2
vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/poly1305/sum_s390x.go
generated
vendored
2
vendor/golang.org/x/crypto/poly1305/sum_s390x.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/poly1305/sum_s390x.s
generated
vendored
2
vendor/golang.org/x/crypto/poly1305/sum_s390x.s
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo,!purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
2
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
@@ -471,7 +471,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
||||
}
|
||||
|
||||
if len(answers) != len(prompts) {
|
||||
return authFailure, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
|
||||
return authFailure, nil, fmt.Errorf("ssh: incorrect number of answers from keyboard-interactive callback %d (expected %d)", len(answers), len(prompts))
|
||||
}
|
||||
responseLength := 1 + 4
|
||||
for _, a := range answers {
|
||||
|
||||
13
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
13
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
@@ -557,8 +557,6 @@ type dhGEXSHA struct {
|
||||
hashFunc crypto.Hash
|
||||
}
|
||||
|
||||
const numMRTests = 64
|
||||
|
||||
const (
|
||||
dhGroupExchangeMinimumBits = 2048
|
||||
dhGroupExchangePreferredBits = 2048
|
||||
@@ -602,15 +600,8 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake
|
||||
gex.p = kexDHGexGroup.P
|
||||
gex.g = kexDHGexGroup.G
|
||||
|
||||
// Check if p is safe by verifing that p and (p-1)/2 are primes
|
||||
one := big.NewInt(1)
|
||||
var pHalf = &big.Int{}
|
||||
pHalf.Rsh(gex.p, 1)
|
||||
if !gex.p.ProbablyPrime(numMRTests) || !pHalf.ProbablyPrime(numMRTests) {
|
||||
return nil, fmt.Errorf("ssh: server provided gex p is not safe")
|
||||
}
|
||||
|
||||
// Check if g is safe by verifing that g > 1 and g < p - 1
|
||||
one := big.NewInt(1)
|
||||
var pMinusOne = &big.Int{}
|
||||
pMinusOne.Sub(gex.p, one)
|
||||
if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {
|
||||
@@ -618,6 +609,8 @@ func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshake
|
||||
}
|
||||
|
||||
// Send GexInit
|
||||
var pHalf = &big.Int{}
|
||||
pHalf.Rsh(gex.p, 1)
|
||||
x, err := rand.Int(randSource, pHalf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
4
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
@@ -572,6 +572,10 @@ userAuthLoop:
|
||||
perms = candidate.perms
|
||||
}
|
||||
case "gssapi-with-mic":
|
||||
if config.GSSAPIWithMICConfig == nil {
|
||||
authErr = errors.New("ssh: gssapi-with-mic auth not configured")
|
||||
break
|
||||
}
|
||||
gssapiConfig := config.GSSAPIWithMICConfig
|
||||
userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload)
|
||||
if err != nil {
|
||||
|
||||
5
vendor/modules.txt
vendored
5
vendor/modules.txt
vendored
@@ -566,7 +566,7 @@ github.com/mgechev/revive/rule
|
||||
# github.com/mholt/archiver/v3 v3.3.0
|
||||
## explicit
|
||||
github.com/mholt/archiver/v3
|
||||
# github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912
|
||||
# github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912 => github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8
|
||||
## explicit
|
||||
github.com/microcosm-cc/bluemonday
|
||||
# github.com/minio/md5-simd v1.1.0
|
||||
@@ -778,7 +778,7 @@ go.mongodb.org/mongo-driver/bson/bsonrw
|
||||
go.mongodb.org/mongo-driver/bson/bsontype
|
||||
go.mongodb.org/mongo-driver/bson/primitive
|
||||
go.mongodb.org/mongo-driver/x/bsonx/bsoncore
|
||||
# golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||
# golang.org/x/crypto v0.0.0-20201217014255-9d1352758620
|
||||
## explicit
|
||||
golang.org/x/crypto/acme
|
||||
golang.org/x/crypto/acme/autocert
|
||||
@@ -979,3 +979,4 @@ xorm.io/xorm/names
|
||||
xorm.io/xorm/schemas
|
||||
xorm.io/xorm/tags
|
||||
# github.com/hashicorp/go-version => github.com/6543/go-version v1.2.4
|
||||
# github.com/microcosm-cc/bluemonday => github.com/lunny/bluemonday v1.0.5-0.20201227154428-ca34796141e8
|
||||
|
||||
@@ -25,6 +25,7 @@ import ActivityTopAuthors from './components/ActivityTopAuthors.vue';
|
||||
import {initNotificationsTable, initNotificationCount} from './features/notification.js';
|
||||
import {createCodeEditor} from './features/codeeditor.js';
|
||||
import {svg, svgs} from './svg.js';
|
||||
import {isMobile} from './utils.js';
|
||||
|
||||
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;
|
||||
|
||||
@@ -385,8 +386,14 @@ function initCommentForm() {
|
||||
if ($('.comment.form').length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
autoSimpleMDE = setCommentSimpleMDE($('.comment.form textarea:not(.review-textarea)'));
|
||||
|
||||
// Don't use simpleMDE on mobile due to multiple bug reports which go unfixed
|
||||
// Other sections rely on it being initialized so just set it back to text area here
|
||||
if (isMobile()) {
|
||||
autoSimpleMDE.toTextArea();
|
||||
}
|
||||
|
||||
initBranchSelector();
|
||||
initCommentPreviewTab($('.comment.form'));
|
||||
initImagePaste($('.comment.form textarea'));
|
||||
@@ -862,25 +869,23 @@ async function initRepository() {
|
||||
const target = $(this).data('target');
|
||||
const quote = $(`#comment-${target}`).text().replace(/\n/g, '\n> ');
|
||||
const content = `> ${quote}\n\n`;
|
||||
|
||||
let $content;
|
||||
let $simplemde = autoSimpleMDE;
|
||||
if ($(this).hasClass('quote-reply-diff')) {
|
||||
const $parent = $(this).closest('.comment-code-cloud');
|
||||
$parent.find('button.comment-form-reply').trigger('click');
|
||||
$content = $parent.find('[name="content"]');
|
||||
if ($content.val() !== '') {
|
||||
$content.val(`${$content.val()}\n\n${content}`);
|
||||
$simplemde = $parent.find('[name="content"]').data('simplemde');
|
||||
}
|
||||
if ($simplemde !== null) {
|
||||
if ($simplemde.value() !== '') {
|
||||
$simplemde.value(`${$simplemde.value()}\n\n${content}`);
|
||||
} else {
|
||||
$content.val(`${content}`);
|
||||
}
|
||||
$content.focus();
|
||||
} else if (autoSimpleMDE !== null) {
|
||||
if (autoSimpleMDE.value() !== '') {
|
||||
autoSimpleMDE.value(`${autoSimpleMDE.value()}\n\n${content}`);
|
||||
} else {
|
||||
autoSimpleMDE.value(`${content}`);
|
||||
$simplemde.value(`${content}`);
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
$simplemde.codemirror.focus();
|
||||
$simplemde.codemirror.setCursor($simplemde.codemirror.lineCount(), 0);
|
||||
});
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
@@ -1043,8 +1048,10 @@ async function initRepository() {
|
||||
$textarea.val($rawContent.text());
|
||||
$simplemde.value($rawContent.text());
|
||||
}
|
||||
$textarea.focus();
|
||||
$simplemde.codemirror.focus();
|
||||
requestAnimationFrame(() => {
|
||||
$textarea.focus();
|
||||
$simplemde.codemirror.focus();
|
||||
});
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
@@ -1055,7 +1062,11 @@ async function initRepository() {
|
||||
$.post($this.data('url'), {
|
||||
_csrf: csrf
|
||||
}).done(() => {
|
||||
const $conversationHolder = $this.closest('.conversation-holder');
|
||||
$(`#${$this.data('comment-id')}`).remove();
|
||||
if ($conversationHolder.length && !$conversationHolder.find('.comment').length) {
|
||||
$conversationHolder.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
@@ -1210,16 +1221,21 @@ function initPullRequestReview() {
|
||||
const form = $(this).parent().find('.comment-form');
|
||||
form.removeClass('hide');
|
||||
const $textarea = form.find('textarea');
|
||||
let $simplemde;
|
||||
if ($textarea.data('simplemde')) {
|
||||
$simplemde = $textarea.data('simplemde');
|
||||
if (!isMobile()) {
|
||||
let $simplemde;
|
||||
if ($textarea.data('simplemde')) {
|
||||
$simplemde = $textarea.data('simplemde');
|
||||
} else {
|
||||
attachTribute($textarea.get(), {mentions: true, emoji: true});
|
||||
$simplemde = setCommentSimpleMDE($textarea);
|
||||
$textarea.data('simplemde', $simplemde);
|
||||
}
|
||||
$textarea.focus();
|
||||
$simplemde.codemirror.focus();
|
||||
} else {
|
||||
attachTribute($textarea.get(), {mentions: true, emoji: true});
|
||||
$simplemde = setCommentSimpleMDE($textarea);
|
||||
$textarea.data('simplemde', $simplemde);
|
||||
$textarea.focus();
|
||||
}
|
||||
$textarea.focus();
|
||||
$simplemde.codemirror.focus();
|
||||
assingMenuAttributes(form.find('.menu'));
|
||||
});
|
||||
// The following part is only for diff views
|
||||
@@ -1286,9 +1302,13 @@ function initPullRequestReview() {
|
||||
const $textarea = commentCloud.find('textarea');
|
||||
attachTribute($textarea.get(), {mentions: true, emoji: true});
|
||||
|
||||
const $simplemde = setCommentSimpleMDE($textarea);
|
||||
$textarea.focus();
|
||||
$simplemde.codemirror.focus();
|
||||
if (!isMobile()) {
|
||||
const $simplemde = setCommentSimpleMDE($textarea);
|
||||
$textarea.focus();
|
||||
$simplemde.codemirror.focus();
|
||||
} else {
|
||||
$textarea.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1334,6 +1354,10 @@ function initWikiForm() {
|
||||
const $editArea = $('.repository.wiki textarea#edit_area');
|
||||
let sideBySideChanges = 0;
|
||||
let sideBySideTimeout = null;
|
||||
if ($editArea.length > 0 && isMobile) {
|
||||
$editArea.css('display', 'inline-block');
|
||||
return;
|
||||
}
|
||||
if ($editArea.length > 0) {
|
||||
const simplemde = new SimpleMDE({
|
||||
autoDownloadFontAwesome: false,
|
||||
@@ -1429,6 +1453,7 @@ function initWikiForm() {
|
||||
name: 'revert-to-textarea',
|
||||
action(e) {
|
||||
e.toTextArea();
|
||||
$editArea.css('display', 'inline-block');
|
||||
},
|
||||
className: 'fa fa-file',
|
||||
title: 'Revert to simple textarea',
|
||||
|
||||
@@ -19,6 +19,11 @@ export function isDarkTheme() {
|
||||
return document.documentElement.classList.contains('theme-arc-green');
|
||||
}
|
||||
|
||||
// returns if mobile device
|
||||
export function isMobile() {
|
||||
return /Mobi/.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
// removes duplicate elements in an array
|
||||
export function uniq(arr) {
|
||||
return Array.from(new Set(arr));
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
url('../fonts/noto-color-emoji/NotoColorEmoji.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@default-fonts: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Twemoji Mozilla";
|
||||
@monospaced-fonts: 'SF Mono', Consolas, Menlo, 'Liberation Mono', Monaco, 'Lucida Console';
|
||||
@default-fonts: system-ui, -apple-system, "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", "Twemoji Mozilla";
|
||||
@monospaced-fonts: "SFMono-Regular", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
|
||||
|
||||
.override-fonts(@fonts) {
|
||||
textarea {
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
margin: 1rem auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* mermaid's errorRenderer seems to unavoidably spew stuff into <body>, hide it */
|
||||
|
||||
Reference in New Issue
Block a user