mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-09 04:30:16 +09:00
Compare commits
8 Commits
v28.1.0
...
release/v28
| Author | SHA1 | Date | |
|---|---|---|---|
| 0001e58e6b | |||
| 79c4237cb2 | |||
| 20f73b2230 | |||
| 175bc89bf9 | |||
| 793e77b073 | |||
| 5018ae1b29 | |||
| c60b13b2dd | |||
| 27bd022b34 |
@@ -37,8 +37,15 @@ jobs:
|
|||||||
# retry snapcraft uploads which can be flaky
|
# retry snapcraft uploads which can be flaky
|
||||||
- name: Publish snap
|
- name: Publish snap
|
||||||
run: |
|
run: |
|
||||||
|
# part-gitea-pull.sh decides what is built, see the comments there:
|
||||||
|
# * grade devel (main or a prerelease tag) goes to latest/edge
|
||||||
|
# * grade stable (a new release tag) goes to latest/stable, and to latest/candidate which marks it as released
|
||||||
|
channel=latest/edge
|
||||||
|
if unsquashfs -cat "$SNAP" meta/snap.yaml | grep -qx 'grade: stable'; then
|
||||||
|
channel=latest/stable,latest/candidate
|
||||||
|
fi
|
||||||
for attempt in 1 2 3 4 5; do
|
for attempt in 1 2 3 4 5; do
|
||||||
snapcraft upload "$SNAP" --release latest/edge && exit 0
|
snapcraft upload "$SNAP" --release "$channel" && exit 0
|
||||||
echo "::warning::snap upload attempt $attempt failed, retrying in 15s"
|
echo "::warning::snap upload attempt $attempt failed, retrying in 15s"
|
||||||
sleep 15
|
sleep 15
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -76,6 +76,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
previous=$(git tag --list --sort=-v:refname | grep -xE 'v[0-9]+\.[0-9]+\.[0-9]+' | grep -A1 -xF "$GITHUB_REF_NAME" | tail -1) # highest stable version below this one
|
previous=$(git tag --list --sort=-v:refname | grep -xE 'v[0-9]+\.[0-9]+\.[0-9]+' | grep -A1 -xF "$GITHUB_REF_NAME" | tail -1) # highest stable version below this one
|
||||||
echo "range=$previous..$GITHUB_SHA" >> "$GITHUB_OUTPUT"
|
echo "range=$previous..$GITHUB_SHA" >> "$GITHUB_OUTPUT"
|
||||||
|
- name: skip reverts and reverted commits in changelog
|
||||||
|
env:
|
||||||
|
RANGE: ${{ steps.range.outputs.range }}
|
||||||
|
run: ./tools/generate-cliffignore.sh "$RANGE" | sort -u > .cliffignore
|
||||||
- uses: orhun/git-cliff-action@a9a95522b26fe6403f7bb24031f21fb573d0f5ff # v4.9.1
|
- uses: orhun/git-cliff-action@a9a95522b26fe6403f7bb24031f21fb573d0f5ff # v4.9.1
|
||||||
with:
|
with:
|
||||||
args: --tag ${{ github.ref_name }} ${{ steps.range.outputs.range }}
|
args: --tag ${{ github.ref_name }} ${{ steps.range.outputs.range }}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SHASUM ?= shasum -a 256
|
|||||||
|
|
||||||
AIR_PACKAGE ?= github.com/air-verse/air@v1.67.4 # renovate: datasource=go
|
AIR_PACKAGE ?= github.com/air-verse/air@v1.67.4 # renovate: datasource=go
|
||||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v4/cmd/editorconfig-checker@v4.0.2 # renovate: datasource=go
|
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v4/cmd/editorconfig-checker@v4.0.2 # renovate: datasource=go
|
||||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.13.2 # renovate: datasource=go
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.14.0 # renovate: datasource=go
|
||||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.17 # renovate: datasource=go
|
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.17 # renovate: datasource=go
|
||||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.8.0 # renovate: datasource=go
|
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.8.0 # renovate: datasource=go
|
||||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.36.6 # renovate: datasource=go
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.36.6 # renovate: datasource=go
|
||||||
|
|||||||
@@ -1098,8 +1098,9 @@ LEVEL = Info
|
|||||||
;; Force ssh:// clone url instead of scp-style uri when default SSH port is used
|
;; Force ssh:// clone url instead of scp-style uri when default SSH port is used
|
||||||
;USE_COMPAT_SSH_URI = false
|
;USE_COMPAT_SSH_URI = false
|
||||||
;;
|
;;
|
||||||
;; Value for the "go get" request returns the repository url as https or ssh, default is https
|
;; Scheme of the returned URL for the "go get" response.
|
||||||
;GO_GET_CLONE_URL_PROTOCOL = https
|
;; Default is "https" if DISABLE_HTTP_GIT=false or SSH is disabled, otherwise "ssh".
|
||||||
|
;GO_GET_CLONE_URL_PROTOCOL =
|
||||||
;;
|
;;
|
||||||
;; Close issues as long as a commit on any branch marks it as fixed
|
;; Close issues as long as a commit on any branch marks it as fixed
|
||||||
;DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
|
;DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module gitea.dev
|
|||||||
|
|
||||||
go 1.27
|
go 1.27
|
||||||
|
|
||||||
toolchain go1.27.1
|
toolchain go1.27.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
connectrpc.com/connect v1.21.0
|
connectrpc.com/connect v1.21.0
|
||||||
|
|||||||
+10
-1
@@ -616,6 +616,15 @@ func ComposeHTTPSCloneURL(ctx context.Context, owner, repo string) string {
|
|||||||
|
|
||||||
// ComposeSSHCloneURL returns SSH clone URL based on the given owner and repository name.
|
// ComposeSSHCloneURL returns SSH clone URL based on the given owner and repository name.
|
||||||
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) string {
|
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) string {
|
||||||
|
return composeSSHCloneURL(doer, ownerName, repoName, setting.Repository.UseCompatSSHURI)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComposeSSHCloneURI is like ComposeSSHCloneURL but always returns the "ssh://" form, because "go get" rejects scp-style addresses
|
||||||
|
func ComposeSSHCloneURI(doer *user_model.User, ownerName, repoName string) string {
|
||||||
|
return composeSSHCloneURL(doer, ownerName, repoName, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func composeSSHCloneURL(doer *user_model.User, ownerName, repoName string, useURI bool) string {
|
||||||
sshUser := setting.SSH.User
|
sshUser := setting.SSH.User
|
||||||
sshDomain := setting.SSH.Domain
|
sshDomain := setting.SSH.Domain
|
||||||
|
|
||||||
@@ -642,7 +651,7 @@ func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) strin
|
|||||||
if ip := net.ParseIP(sshHost); ip != nil && ip.To4() == nil {
|
if ip := net.ParseIP(sshHost); ip != nil && ip.To4() == nil {
|
||||||
sshHost = "[" + sshHost + "]" // for IPv6 address, wrap it with brackets
|
sshHost = "[" + sshHost + "]" // for IPv6 address, wrap it with brackets
|
||||||
}
|
}
|
||||||
if setting.Repository.UseCompatSSHURI {
|
if useURI {
|
||||||
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName))
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ func TestComposeSSHCloneURL(t *testing.T) {
|
|||||||
assert.Equal(t, "git@domain:user/repo.git", ComposeSSHCloneURL(&user_model.User{Name: "doer"}, "user", "repo"))
|
assert.Equal(t, "git@domain:user/repo.git", ComposeSSHCloneURL(&user_model.User{Name: "doer"}, "user", "repo"))
|
||||||
setting.Repository.UseCompatSSHURI = true
|
setting.Repository.UseCompatSSHURI = true
|
||||||
assert.Equal(t, "ssh://git@domain/user/repo.git", ComposeSSHCloneURL(&user_model.User{Name: "doer"}, "user", "repo"))
|
assert.Equal(t, "ssh://git@domain/user/repo.git", ComposeSSHCloneURL(&user_model.User{Name: "doer"}, "user", "repo"))
|
||||||
|
setting.Repository.UseCompatSSHURI = false
|
||||||
|
assert.Equal(t, "ssh://git@domain/user/repo.git", ComposeSSHCloneURI(nil, "user", "repo"))
|
||||||
// test SSH_DOMAIN while use non-standard SSH port
|
// test SSH_DOMAIN while use non-standard SSH port
|
||||||
setting.SSH.Port = 123
|
setting.SSH.Port = 123
|
||||||
setting.Repository.UseCompatSSHURI = false
|
setting.Repository.UseCompatSSHURI = false
|
||||||
|
|||||||
@@ -151,16 +151,28 @@ func TestListEmails(t *testing.T) {
|
|||||||
|
|
||||||
func TestEmailAddressValidate(t *testing.T) {
|
func TestEmailAddressValidate(t *testing.T) {
|
||||||
cases := map[string]bool{
|
cases := map[string]bool{
|
||||||
"": false,
|
"": false,
|
||||||
"root@localhost": true,
|
"@a": false,
|
||||||
"user@[192.168.1.2]": true,
|
|
||||||
"@a": false,
|
// "_" shouldn't appear in domain but can appear in hostname, since we can't stop site admins from doing so, just accept it
|
||||||
"abc@gmail.com": true,
|
"root@local_host": true,
|
||||||
"abc@gmail.com\n": false,
|
"root@localhost": true,
|
||||||
|
"root@LOCALHOST": true,
|
||||||
|
|
||||||
|
"user@[192.168.1.2]": true,
|
||||||
|
"user@[IPv6:FFff::1]": true,
|
||||||
|
|
||||||
|
"abc@gmail.com": true,
|
||||||
|
"abc@gmail.com.": false,
|
||||||
|
"abc@gmail.com-": false,
|
||||||
|
"abc@gmail.com\n": false,
|
||||||
|
"abc@gmail..com": false,
|
||||||
|
"abc@gmail com": false,
|
||||||
|
"abc@gmail*com": false,
|
||||||
|
|
||||||
"Foo <foo@bar.com>": false,
|
"Foo <foo@bar.com>": false,
|
||||||
"abc@gmail.com (x)": false,
|
"abc@gmail.com (x)": false,
|
||||||
"jürgen@example.com": false,
|
"jürgen@example.com": false, // utf8 address is not supported yet
|
||||||
"a@foo_bar.com": false,
|
|
||||||
}
|
}
|
||||||
for tc, isValid := range cases {
|
for tc, isValid := range cases {
|
||||||
t.Run(tc, func(t *testing.T) {
|
t.Run(tc, func(t *testing.T) {
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ func NewEmbeddedFS(data []byte) fs.ReadDirFS {
|
|||||||
efs := &embeddedFS{data: data, files: make(map[string]*embeddedFileInfo)}
|
efs := &embeddedFS{data: data, files: make(map[string]*embeddedFileInfo)}
|
||||||
efs.meta = sync.OnceValue(func() *EmbeddedMeta {
|
efs.meta = sync.OnceValue(func() *EmbeddedMeta {
|
||||||
var meta EmbeddedMeta
|
var meta EmbeddedMeta
|
||||||
p := bytes.LastIndexByte(data, '\n')
|
_, metaJSON, ok := bytes.CutLast(data, []byte{'\n'})
|
||||||
if p < 0 {
|
if !ok {
|
||||||
return &meta
|
return &meta
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(data[p+1:], &meta); err != nil {
|
if err := json.Unmarshal(metaJSON, &meta); err != nil {
|
||||||
panic("embedded file is not valid")
|
panic("embedded file is not valid")
|
||||||
}
|
}
|
||||||
return &meta
|
return &meta
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ func ReloadTemplates(ctx context.Context) ResponseExtra {
|
|||||||
|
|
||||||
// FlushOptions represents the options for the flush call
|
// FlushOptions represents the options for the flush call
|
||||||
type FlushOptions struct {
|
type FlushOptions struct {
|
||||||
Timeout time.Duration
|
Timeout int64
|
||||||
NonBlocking bool
|
NonBlocking bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushQueues calls the internal flush-queues function
|
// FlushQueues calls the internal flush-queues function
|
||||||
func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) ResponseExtra {
|
func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/flush-queues"
|
reqURL := setting.LocalURL + "api/internal/manager/flush-queues"
|
||||||
req := newInternalRequestAPI(ctx, reqURL, "POST", FlushOptions{Timeout: timeout, NonBlocking: nonBlocking})
|
req := newInternalRequestAPI(ctx, reqURL, "POST", FlushOptions{Timeout: int64(timeout), NonBlocking: nonBlocking})
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
req.SetReadWriteTimeout(timeout + 10*time.Second)
|
req.SetReadWriteTimeout(timeout + 10*time.Second)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) {
|
|||||||
sec := rootCfg.Section("repository")
|
sec := rootCfg.Section("repository")
|
||||||
Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool()
|
Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool()
|
||||||
Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool()
|
Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool()
|
||||||
Repository.GoGetCloneURLProtocol = sec.Key("GO_GET_CLONE_URL_PROTOCOL").MustString("https")
|
Repository.GoGetCloneURLProtocol = sec.Key("GO_GET_CLONE_URL_PROTOCOL").String()
|
||||||
// MAX_CREATION_LIMIT is a shortcut that sets the default for the two per-type limits below.
|
// MAX_CREATION_LIMIT is a shortcut that sets the default for the two per-type limits below.
|
||||||
// USER_/ORG_MAX_CREATION_LIMIT take precedence when explicitly set.
|
// USER_/ORG_MAX_CREATION_LIMIT take precedence when explicitly set.
|
||||||
Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1) // FIXME: INI-MUST-SIDE-EFFECT
|
Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1) // FIXME: INI-MUST-SIDE-EFFECT
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import (
|
|||||||
|
|
||||||
"gitea.dev/modules/glob"
|
"gitea.dev/modules/glob"
|
||||||
"gitea.dev/modules/setting"
|
"gitea.dev/modules/setting"
|
||||||
|
|
||||||
"golang.org/x/net/idna"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type globalVarsStruct struct {
|
type globalVarsStruct struct {
|
||||||
@@ -24,6 +22,8 @@ type globalVarsStruct struct {
|
|||||||
invalidUsernamePattern *regexp.Regexp
|
invalidUsernamePattern *regexp.Regexp
|
||||||
validBadgeSlugPattern *regexp.Regexp
|
validBadgeSlugPattern *regexp.Regexp
|
||||||
invalidBadgeSlugPattern *regexp.Regexp
|
invalidBadgeSlugPattern *regexp.Regexp
|
||||||
|
validEmailHostName *regexp.Regexp
|
||||||
|
validEmailHostIP *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
var globalVars = sync.OnceValue(func() *globalVarsStruct {
|
var globalVars = sync.OnceValue(func() *globalVarsStruct {
|
||||||
@@ -33,6 +33,8 @@ var globalVars = sync.OnceValue(func() *globalVarsStruct {
|
|||||||
invalidUsernamePattern: regexp.MustCompile(`[-._]{2,}|[-._]$`), // No consecutive or trailing non-alphanumeric chars
|
invalidUsernamePattern: regexp.MustCompile(`[-._]{2,}|[-._]$`), // No consecutive or trailing non-alphanumeric chars
|
||||||
validBadgeSlugPattern: regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]*$`),
|
validBadgeSlugPattern: regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]*$`),
|
||||||
invalidBadgeSlugPattern: regexp.MustCompile(`[-._]{2,}|[-._]$`),
|
invalidBadgeSlugPattern: regexp.MustCompile(`[-._]{2,}|[-._]$`),
|
||||||
|
validEmailHostName: regexp.MustCompile(`^[a-zA-Z0-9][-.\w]*$`),
|
||||||
|
validEmailHostIP: regexp.MustCompile(`(?i)^\[([0-9.]+|ipv6:[0-9a-f:.]+)\]$`),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -124,10 +126,12 @@ func IsEmailAddressValid(email string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, domain, _ := strings.Cut(email, "@")
|
_, domain, _ := strings.Cut(email, "@")
|
||||||
if strings.HasPrefix(domain, "[") {
|
if !globalVars().validEmailHostName.MatchString(domain) && !globalVars().validEmailHostIP.MatchString(domain) {
|
||||||
// address like "foo@[192.168.1.2]"
|
return false
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
_, err = idna.Registration.ToASCII(domain)
|
if strings.HasPrefix(domain, "-") || strings.HasSuffix(domain, "-") ||
|
||||||
return err == nil
|
strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,8 +135,8 @@ func shortenFilename(filename, fallback string) string {
|
|||||||
if filename == "" {
|
if filename == "" {
|
||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
if lastIndex := strings.LastIndexByte(filename, '/'); lastIndex >= 0 {
|
if dir, _, ok := strings.CutLast(filename, "/"); ok {
|
||||||
if secondLastIndex := strings.LastIndexByte(filename[:lastIndex], '/'); secondLastIndex >= 0 {
|
if secondLastIndex := strings.LastIndexByte(dir, '/'); secondLastIndex >= 0 {
|
||||||
return filename[secondLastIndex+1:]
|
return filename[secondLastIndex+1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package private
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gitea.dev/models/db"
|
"gitea.dev/models/db"
|
||||||
"gitea.dev/modules/graceful"
|
"gitea.dev/modules/graceful"
|
||||||
@@ -34,7 +35,7 @@ func FlushQueues(ctx *context.PrivateContext) {
|
|||||||
// Save the hammer ctx here - as a new one is created each time you call this.
|
// Save the hammer ctx here - as a new one is created each time you call this.
|
||||||
baseCtx := graceful.GetManager().HammerContext()
|
baseCtx := graceful.GetManager().HammerContext()
|
||||||
go func() {
|
go func() {
|
||||||
err := queue.GetManager().FlushAll(baseCtx, opts.Timeout)
|
err := queue.GetManager().FlushAll(baseCtx, time.Duration(opts.Timeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Flushing request timed-out with error: %v", err)
|
log.Error("Flushing request timed-out with error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ func FlushQueues(ctx *context.PrivateContext) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := queue.GetManager().FlushAll(ctx, opts.Timeout)
|
err := queue.GetManager().FlushAll(ctx, time.Duration(opts.Timeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.PrivateUserErrorf(http.StatusRequestTimeout, "%v", err)
|
ctx.PrivateUserErrorf(http.StatusRequestTimeout, "%v", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ func OIDCWellKnown(ctx *context.Context) {
|
|||||||
"introspection_endpoint": oidcBaseUrl + "/login/oauth/introspect",
|
"introspection_endpoint": oidcBaseUrl + "/login/oauth/introspect",
|
||||||
"response_types_supported": []string{
|
"response_types_supported": []string{
|
||||||
"code",
|
"code",
|
||||||
"id_token",
|
|
||||||
},
|
},
|
||||||
"id_token_signing_alg_values_supported": []string{
|
"id_token_signing_alg_values_supported": []string{
|
||||||
oauth2_provider.DefaultSigningKey.SigningMethod().Alg(),
|
oauth2_provider.DefaultSigningKey.SigningMethod().Alg(),
|
||||||
|
|||||||
@@ -69,13 +69,7 @@ func goGet(ctx *context.Context) {
|
|||||||
|
|
||||||
goGetImport := context.ComposeGoGetImport(ctx, ownerName, trimmedRepoName)
|
goGetImport := context.ComposeGoGetImport(ctx, ownerName, trimmedRepoName)
|
||||||
|
|
||||||
var cloneURL string
|
goImportContent := fmt.Sprintf("%s git %s", goGetImport, context.ComposeGoGetCloneURL(ctx, ownerName, trimmedRepoName))
|
||||||
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
|
||||||
cloneURL = repo_model.ComposeSSHCloneURL(ctx.Doer, ownerName, repoName)
|
|
||||||
} else {
|
|
||||||
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, ownerName, repoName)
|
|
||||||
}
|
|
||||||
goImportContent := fmt.Sprintf("%s git %s", goGetImport, cloneURL /*CloneLink*/)
|
|
||||||
goSourceContent := fmt.Sprintf("%s _ %s %s", goGetImport, prefix+"{/dir}" /*GoDocDirectory*/, prefix+"{/dir}/{file}#L{line}" /*GoDocFile*/)
|
goSourceContent := fmt.Sprintf("%s _ %s %s", goGetImport, prefix+"{/dir}" /*GoDocDirectory*/, prefix+"{/dir}/{file}#L{line}" /*GoDocFile*/)
|
||||||
goGetCli := fmt.Sprintf("go get %s%s", insecure, goGetImport)
|
goGetCli := fmt.Sprintf("go get %s%s", insecure, goGetImport)
|
||||||
|
|
||||||
|
|||||||
@@ -197,7 +197,6 @@ func verifyAuthWithOptionsWeb(options *common.VerifyOptions) func(ctx *context.C
|
|||||||
ctx.HTTPError(http.StatusUnauthorized, ctx.Locale.TrString("auth.must_change_password"))
|
ctx.HTTPError(http.StatusUnauthorized, ctx.Locale.TrString("auth.must_change_password"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
|
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
|
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -389,6 +389,15 @@ func ComposeGoGetImport(ctx context.Context, owner, repo string) string {
|
|||||||
return path.Join(curAppURL.Host, setting.AppSubURL, url.PathEscape(owner), url.PathEscape(repo))
|
return path.Join(curAppURL.Host, setting.AppSubURL, url.PathEscape(owner), url.PathEscape(repo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ComposeGoGetCloneURL returns the clone URL for the go-import meta content.
|
||||||
|
func ComposeGoGetCloneURL(ctx *Context, owner, repo string) string {
|
||||||
|
useSSH := setting.Repository.GoGetCloneURLProtocol == "ssh" || (setting.Repository.DisableHTTPGit && !setting.SSH.Disabled)
|
||||||
|
if useSSH {
|
||||||
|
return repo_model.ComposeSSHCloneURI(ctx.Doer, owner, repo)
|
||||||
|
}
|
||||||
|
return repo_model.ComposeHTTPSCloneURL(ctx, owner, repo)
|
||||||
|
}
|
||||||
|
|
||||||
// EarlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
// EarlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
||||||
// if user does not have actual access to the requested repository,
|
// if user does not have actual access to the requested repository,
|
||||||
// or the owner or repository does not exist at all.
|
// or the owner or repository does not exist at all.
|
||||||
@@ -402,13 +411,7 @@ func EarlyResponseForGoGetMeta(ctx *Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var cloneURL string
|
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(ctx, username, reponame), ComposeGoGetCloneURL(ctx, username, reponame))
|
||||||
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
|
||||||
cloneURL = repo_model.ComposeSSHCloneURL(ctx.Doer, username, reponame)
|
|
||||||
} else {
|
|
||||||
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, username, reponame)
|
|
||||||
}
|
|
||||||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(ctx, username, reponame), cloneURL)
|
|
||||||
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
||||||
ctx.PlainText(http.StatusOK, htmlMeta)
|
ctx.PlainText(http.StatusOK, htmlMeta)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,6 @@ type AdminEditUserForm struct {
|
|||||||
// AdminDashboardForm form for admin dashboard operations
|
// AdminDashboardForm form for admin dashboard operations
|
||||||
type AdminDashboardForm struct {
|
type AdminDashboardForm struct {
|
||||||
middleware.FormDefaultValidator
|
middleware.FormDefaultValidator
|
||||||
Op string `binding:"required"`
|
Op string `binding:"Required"`
|
||||||
From string
|
From string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -571,12 +571,6 @@ type AddTimeManuallyForm struct {
|
|||||||
Minutes int `binding:"Range(0,1000)"`
|
Minutes int `binding:"Range(0,1000)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveTopicForm form for save topics for repository
|
|
||||||
type SaveTopicForm struct {
|
|
||||||
middleware.FormDefaultValidator
|
|
||||||
Topics []string `binding:"topics;Required;"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDeployTokenForm form for adding a deploy token to a repository
|
// AddDeployTokenForm form for adding a deploy token to a repository
|
||||||
type AddDeployTokenForm struct {
|
type AddDeployTokenForm struct {
|
||||||
middleware.FormDefaultValidator
|
middleware.FormDefaultValidator
|
||||||
|
|||||||
@@ -201,9 +201,12 @@ func (telegramConvertor) WorkflowJob(p *api.WorkflowJobPayload) (TelegramPayload
|
|||||||
|
|
||||||
func createTelegramPayloadHTML(msgHTML string) TelegramPayload {
|
func createTelegramPayloadHTML(msgHTML string) TelegramPayload {
|
||||||
// https://core.telegram.org/bots/api#formatting-options
|
// https://core.telegram.org/bots/api#formatting-options
|
||||||
|
sanitized := strings.TrimSpace(string(markup.Sanitize(msgHTML)))
|
||||||
|
// Rich messages collapse bare newlines like HTML, so keep line breaks as <br>.
|
||||||
|
sanitized = strings.NewReplacer("\r\n", "<br>", "\r", "<br>", "\n", "<br>").Replace(sanitized)
|
||||||
return TelegramPayload{
|
return TelegramPayload{
|
||||||
RichMessage: InputRichMessage{
|
RichMessage: InputRichMessage{
|
||||||
HTML: strings.TrimSpace(string(markup.Sanitize(msgHTML))),
|
HTML: sanitized,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ func TestTelegramPayload(t *testing.T) {
|
|||||||
}, p)
|
}, p)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Line breaks are kept in rich messages", func(t *testing.T) {
|
||||||
|
// Rich messages collapse bare newlines, so they must become <br>.
|
||||||
|
p := createTelegramPayloadHTML("first line\r\nsecond line\nthird line")
|
||||||
|
assert.Equal(t, "first line<br>second line<br>third line", p.RichMessage.HTML)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Create", func(t *testing.T) {
|
t.Run("Create", func(t *testing.T) {
|
||||||
p := createTestPayload()
|
p := createTestPayload()
|
||||||
|
|
||||||
@@ -60,9 +66,7 @@ func TestTelegramPayload(t *testing.T) {
|
|||||||
pl, err := tc.Push(p)
|
pl, err := tc.Push(p)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>:<a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a>] 2 new commits
|
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>:<a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a>] 2 new commits<br>[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1<br>[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1`, pl.RichMessage.HTML)
|
||||||
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1
|
|
||||||
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1`, pl.RichMessage.HTML)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Issue", func(t *testing.T) {
|
t.Run("Issue", func(t *testing.T) {
|
||||||
@@ -72,9 +76,7 @@ func TestTelegramPayload(t *testing.T) {
|
|||||||
pl, err := tc.Issue(p)
|
pl, err := tc.Issue(p)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Issue opened: <a href="http://localhost:3000/test/repo/issues/2" rel="nofollow">#2 crash</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
|
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Issue opened: <a href="http://localhost:3000/test/repo/issues/2" rel="nofollow">#2 crash</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a><br><br>issue body`, pl.RichMessage.HTML)
|
||||||
|
|
||||||
issue body`, pl.RichMessage.HTML)
|
|
||||||
|
|
||||||
p.Action = api.HookIssueClosed
|
p.Action = api.HookIssueClosed
|
||||||
pl, err = tc.Issue(p)
|
pl, err = tc.Issue(p)
|
||||||
@@ -89,8 +91,7 @@ issue body`, pl.RichMessage.HTML)
|
|||||||
pl, err := tc.IssueComment(p)
|
pl, err := tc.IssueComment(p)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] New comment on issue <a href="http://localhost:3000/test/repo/issues/2" rel="nofollow">#2 crash</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
|
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] New comment on issue <a href="http://localhost:3000/test/repo/issues/2" rel="nofollow">#2 crash</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a><br>more info needed`, pl.RichMessage.HTML)
|
||||||
more info needed`, pl.RichMessage.HTML)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PullRequest", func(t *testing.T) {
|
t.Run("PullRequest", func(t *testing.T) {
|
||||||
@@ -99,8 +100,7 @@ more info needed`, pl.RichMessage.HTML)
|
|||||||
pl, err := tc.PullRequest(p)
|
pl, err := tc.PullRequest(p)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Pull request opened: <a href="http://localhost:3000/test/repo/pulls/12" rel="nofollow">#12 Fix bug</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
|
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] Pull request opened: <a href="http://localhost:3000/test/repo/pulls/12" rel="nofollow">#12 Fix bug</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a><br>fixes bug #2`, pl.RichMessage.HTML)
|
||||||
fixes bug #2`, pl.RichMessage.HTML)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PullRequestComment", func(t *testing.T) {
|
t.Run("PullRequestComment", func(t *testing.T) {
|
||||||
@@ -109,8 +109,7 @@ fixes bug #2`, pl.RichMessage.HTML)
|
|||||||
pl, err := tc.IssueComment(p)
|
pl, err := tc.IssueComment(p)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] New comment on pull request <a href="http://localhost:3000/test/repo/pulls/12" rel="nofollow">#12 Fix bug</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a>
|
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>] New comment on pull request <a href="http://localhost:3000/test/repo/pulls/12" rel="nofollow">#12 Fix bug</a> by <a href="https://try.gitea.io/user1" rel="nofollow">user1</a><br>changes requested`, pl.RichMessage.HTML)
|
||||||
changes requested`, pl.RichMessage.HTML)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Review", func(t *testing.T) {
|
t.Run("Review", func(t *testing.T) {
|
||||||
@@ -120,8 +119,7 @@ changes requested`, pl.RichMessage.HTML)
|
|||||||
pl, err := tc.Review(p, webhook_module.HookEventPullRequestReviewApproved)
|
pl, err := tc.Review(p, webhook_module.HookEventPullRequestReviewApproved)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, `[test/repo] Pull request review approved: #12 Fix bug
|
assert.Equal(t, `[test/repo] Pull request review approved: #12 Fix bug<br>good job`, pl.RichMessage.HTML)
|
||||||
good job`, pl.RichMessage.HTML)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Repository", func(t *testing.T) {
|
t.Run("Repository", func(t *testing.T) {
|
||||||
@@ -206,7 +204,5 @@ func TestTelegramJSONPayload(t *testing.T) {
|
|||||||
var body TelegramPayload
|
var body TelegramPayload
|
||||||
err = json.NewDecoder(req.Body).Decode(&body)
|
err = json.NewDecoder(req.Body).Decode(&body)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>:<a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a>] 2 new commits
|
assert.Equal(t, `[<a href="http://localhost:3000/test/repo" rel="nofollow">test/repo</a>:<a href="http://localhost:3000/test/repo/src/test" rel="nofollow">test</a>] 2 new commits<br>[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1<br>[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1`, body.RichMessage.HTML)
|
||||||
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1
|
|
||||||
[<a href="http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778" rel="nofollow">2020558</a>] commit message - user1`, body.RichMessage.HTML)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# How it works:
|
# How it works:
|
||||||
# * snapcraft.io checks out the default branch (e.g.: main during 1.27 dev period)
|
# * release-nightly-snapcraft.yml builds the snap on every push to the default branch (e.g.: main during 1.27 dev period)
|
||||||
# * "override-pull" step gets the latest tag by date (e.g.: v1.26.1)
|
# * "override-pull" step gets the latest tag by date (e.g.: v1.26.1)
|
||||||
# * use "snap info gitea" to get the latest released tag
|
# * use "snap info gitea" to get the latest released tag, which is the version in the "latest/candidate" channel
|
||||||
# * if the latest tag is not released to stable, checkout that tag and build it for "stable"
|
# * if the latest tag is not released yet, checkout that tag and build it with grade "stable",
|
||||||
# * otherwise, build the main branch for "devel"
|
# the workflow publishes it to "latest/stable" and "latest/candidate"
|
||||||
|
# * otherwise, build the main branch with grade "devel", the workflow publishes it to "latest/edge"
|
||||||
# * "override-build" step uses build script from the checked out commit to build
|
# * "override-build" step uses build script from the checked out commit to build
|
||||||
# This approach highly depends on the "main" branch's push.
|
# This approach highly depends on the "main" branch's push: a new tag is only published by the next push after it.
|
||||||
|
|
||||||
# To debug the logic:
|
# To debug the logic:
|
||||||
# * last_committed_tag=v1.26.1 last_released_tag=v1.26.0 ./snap/part-gitea-pull.sh
|
# * last_committed_tag=v1.26.1 last_released_tag=v1.26.0 ./snap/part-gitea-pull.sh
|
||||||
|
|||||||
@@ -44,8 +44,8 @@
|
|||||||
<div class="navbar-right">
|
<div class="navbar-right">
|
||||||
{{if and .IsSigned .MustChangePassword}}
|
{{if and .IsSigned .MustChangePassword}}
|
||||||
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
|
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
|
||||||
<span class="text">
|
<span class="flex-text-block">
|
||||||
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
|
{{ctx.AvatarUtils.Avatar .SignedUser 24}}
|
||||||
<span class="only-mobile">{{.SignedUser.Name}}</span>
|
<span class="only-mobile">{{.SignedUser.Name}}</span>
|
||||||
<span class="not-mobile flex-text-block">{{svg "octicon-triangle-down"}}</span>
|
<span class="not-mobile flex-text-block">{{svg "octicon-triangle-down"}}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{{- $itemExtraClass := .ItemExtraClass -}}
|
{{- $itemExtraClass := .ItemExtraClass -}}
|
||||||
{{- $data := .PageGlobalData -}}
|
{{- $data := .PageGlobalData -}}
|
||||||
{{if and $data $data.IsSigned}}{{/* data may not exist, for example: rendering 503 page before the PageGlobalData middleware */}}
|
{{if and $data $data.IsSigned (not ctx.RootData.MustChangePassword)}}{{/* data may not exist, for example: rendering 503 page before the PageGlobalData middleware */}}
|
||||||
{{- $activeStopwatch := call $data.GetActiveStopwatch -}}
|
{{- $activeStopwatch := call $data.GetActiveStopwatch -}}
|
||||||
{{- $notificationUnreadCount := call $data.GetNotificationUnreadCount -}}
|
{{- $notificationUnreadCount := call $data.GetNotificationUnreadCount -}}
|
||||||
{{/* always rendered so a real-time push can reveal it without a reload */}}
|
{{/* always rendered so a real-time push can reveal it without a reload */}}
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ func TestGoGetForSSH(t *testing.T) {
|
|||||||
</html>`, setting.AppDomain, setting.HTTPPort, setting.AppURL, setting.SSH.Domain, setting.SSH.Port)
|
</html>`, setting.AppDomain, setting.HTTPPort, setting.AppURL, setting.SSH.Domain, setting.SSH.Port)
|
||||||
|
|
||||||
assert.Equal(t, expected, resp.Body.String())
|
assert.Equal(t, expected, resp.Body.String())
|
||||||
|
|
||||||
|
// go rejects scp-style addresses, so the standard port must still produce an ssh:// URL
|
||||||
|
defer test.MockVariableValue(&setting.SSH.Port, 22)()
|
||||||
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
assert.Contains(t, resp.Body.String(), fmt.Sprintf(`git ssh://git@%s/blah/glah.git">`, setting.SSH.Domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGoGetPrivateRepoBranchNotLeaked ensures the go-get meta endpoint does not disclose a
|
// TestGoGetPrivateRepoBranchNotLeaked ensures the go-get meta endpoint does not disclose a
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ func TestOAuth2(t *testing.T) {
|
|||||||
t.Run("AuthorizeNoClientID", testAuthorizeNoClientID)
|
t.Run("AuthorizeNoClientID", testAuthorizeNoClientID)
|
||||||
t.Run("AuthorizeUnregisteredRedirect", testAuthorizeUnregisteredRedirect)
|
t.Run("AuthorizeUnregisteredRedirect", testAuthorizeUnregisteredRedirect)
|
||||||
t.Run("AuthorizeUnsupportedResponseType", testAuthorizeUnsupportedResponseType)
|
t.Run("AuthorizeUnsupportedResponseType", testAuthorizeUnsupportedResponseType)
|
||||||
|
t.Run("AuthorizeUnsupportedResponseTypeIDToken", testAuthorizeUnsupportedResponseTypeIDToken)
|
||||||
t.Run("AuthorizeUnsupportedCodeChallengeMethod", testAuthorizeUnsupportedCodeChallengeMethod)
|
t.Run("AuthorizeUnsupportedCodeChallengeMethod", testAuthorizeUnsupportedCodeChallengeMethod)
|
||||||
t.Run("AuthorizeLoginRedirect", testAuthorizeLoginRedirect)
|
t.Run("AuthorizeLoginRedirect", testAuthorizeLoginRedirect)
|
||||||
t.Run("AuthorizeShow", testAuthorizeShow)
|
t.Run("AuthorizeShow", testAuthorizeShow)
|
||||||
@@ -163,6 +164,16 @@ func testAuthorizeUnsupportedResponseType(t *testing.T) {
|
|||||||
assert.Equal(t, "Only code response type is supported.", u.Query().Get("error_description"))
|
assert.Equal(t, "Only code response type is supported.", u.Query().Get("error_description"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAuthorizeUnsupportedResponseTypeIDToken(t *testing.T) {
|
||||||
|
req := NewRequest(t, "GET", "/login/oauth/authorize?client_id=da7da3ba-9a13-4167-856f-3899de0b0138&redirect_uri=https://example.com&response_type=id_token&state=thestate")
|
||||||
|
ctx := loginUser(t, "user1")
|
||||||
|
resp := ctx.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
u, err := resp.Result().Location()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "unsupported_response_type", u.Query().Get("error"))
|
||||||
|
assert.Equal(t, "Only code response type is supported.", u.Query().Get("error_description"))
|
||||||
|
}
|
||||||
|
|
||||||
func testAuthorizeUnsupportedCodeChallengeMethod(t *testing.T) {
|
func testAuthorizeUnsupportedCodeChallengeMethod(t *testing.T) {
|
||||||
req := NewRequest(t, "GET", "/login/oauth/authorize?client_id=da7da3ba-9a13-4167-856f-3899de0b0138&redirect_uri=https://example.com&response_type=code&state=thestate&code_challenge_method=UNEXPECTED")
|
req := NewRequest(t, "GET", "/login/oauth/authorize?client_id=da7da3ba-9a13-4167-856f-3899de0b0138&redirect_uri=https://example.com&response_type=code&state=thestate&code_challenge_method=UNEXPECTED")
|
||||||
ctx := loginUser(t, "user1")
|
ctx := loginUser(t, "user1")
|
||||||
|
|||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Prints the revert commits in the given range and the commits they revert, for git-cliff's .cliffignore
|
||||||
|
range="${1:?usage: $0 <revision-range>}"
|
||||||
|
commits=$(git log --format='%H %s' "$range")
|
||||||
|
|
||||||
|
shopt -s nocasematch
|
||||||
|
while read -r sha subject; do
|
||||||
|
[[ "$subject" == revert* ]] || continue
|
||||||
|
echo "$sha"
|
||||||
|
for pr in $(git show -s --format=%B "$sha" | grep -i revert | grep -oE '(#|/pull/)[0-9]+' | grep -oE '[0-9]+' || true); do
|
||||||
|
grep -F "(#$pr)" <<< "$commits" | cut -d' ' -f1 || true
|
||||||
|
done
|
||||||
|
done <<< "$commits"
|
||||||
@@ -125,7 +125,8 @@
|
|||||||
.markup ol,
|
.markup ol,
|
||||||
.markup dl,
|
.markup dl,
|
||||||
.markup table,
|
.markup table,
|
||||||
.markup pre {
|
.markup pre,
|
||||||
|
.markup math[display="block" i] {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user