mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-15 12:33:45 +09:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e084341fe | ||
|
|
7d75eede04 | ||
|
|
3db98bef99 | ||
|
|
484fe075f4 | ||
|
|
de3216ee55 | ||
|
|
353d88a42e | ||
|
|
a17fce31a9 | ||
|
|
71e1ebfa60 | ||
|
|
afe9d2cadd | ||
|
|
012e45a4c1 | ||
|
|
d25ff0d695 | ||
|
|
6eaebda1b5 | ||
|
|
6100935a77 | ||
|
|
6de75224de | ||
|
|
9086916eb7 | ||
|
|
877040e652 | ||
|
|
91f5be889a | ||
|
|
a818a48c76 | ||
|
|
76e1c130fb | ||
|
|
148a417774 | ||
|
|
6081948ef0 | ||
|
|
48bd54286c | ||
|
|
c69b3b65f3 | ||
|
|
fe91d9617b | ||
|
|
711ca52f1f | ||
|
|
a15f0cb010 | ||
|
|
2051f850ef | ||
|
|
3ae4c4898b | ||
|
|
3a77465e4e | ||
|
|
fc8c23edb7 | ||
|
|
31df892059 |
37
CHANGELOG.md
37
CHANGELOG.md
@@ -4,6 +4,43 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.15.9](https://github.com/go-gitea/gitea/releases/tag/v1.15.9) - 2021-12-30
|
||||
|
||||
* BUGFIXES
|
||||
* Fix wrong redirect on org labels (#18128) (#18134)
|
||||
* Fix: unstable sort skips/duplicates issues across pages (#18094) (#18095)
|
||||
* Revert "Fix delete u2f keys bug (#18042)" (#18107)
|
||||
* Migrating wiki don't require token, so we should move it out of the require form (#17645) (#18104)
|
||||
* Prevent NPE if gitea uploader fails to open url (#18080) (#18101)
|
||||
* Reset locale on login (#17734) (#18100)
|
||||
* Correctly handle failed migrations (#17575) (#18099)
|
||||
* Instead of using routerCtx just escape the url before routing (#18086) (#18098)
|
||||
* Quote references to the user table in consistency checks (#18072) (#18073)
|
||||
* Add NotFound handler (#18062) (#18067)
|
||||
* Ensure that git repository is closed before transfer (#18049) (#18057)
|
||||
* Use common sessioner for API and web routes (#18114)
|
||||
* TRANSLATION
|
||||
* Fix code search result hint on zh-CN (#18053)
|
||||
|
||||
## [1.15.8](https://github.com/go-gitea/gitea/releases/tag/v1.15.8) - 2021-12-20
|
||||
|
||||
* BUGFIXES
|
||||
* Move POST /{username}/action/{action} to simply POST /{username} (#18045) (#18046)
|
||||
* Fix delete u2f keys bug (#18040) (#18042)
|
||||
* Reset Session ID on login (#18018) (#18041)
|
||||
* Prevent off-by-one error on comments on newly appended lines (#18029) (#18035)
|
||||
* Stop printing 03d after escaped characters in logs (#18030) (#18034)
|
||||
* Reset locale on login (#18023) (#18025)
|
||||
* Fix reset password email template (#17025) (#18022)
|
||||
* Fix outType on gitea dump (#18000) (#18016)
|
||||
* Ensure complexity, minlength and isPwned are checked on password setting (#18005) (#18015)
|
||||
* Fix rename notification bug (#18011)
|
||||
* Prevent double decoding of % in url params (#17997) (#18001)
|
||||
* Prevent hang in git cat-file if the repository is not a valid repository (Partial #17991) (#17992)
|
||||
* Prevent deadlock in create issue (#17970) (#17982)
|
||||
* TESTING
|
||||
* Use non-expiring key. (#17984) (#17985)
|
||||
|
||||
## [1.15.7](https://github.com/go-gitea/gitea/releases/tag/v1.15.7) - 2021-12-01
|
||||
|
||||
* ENHANCEMENTS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
###################################
|
||||
#Build stage
|
||||
FROM golang:1.16-alpine3.13 AS build-env
|
||||
FROM techknowlogick/go:1.16-alpine3.13 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
###################################
|
||||
#Build stage
|
||||
FROM golang:1.16-alpine3.13 AS build-env
|
||||
FROM techknowlogick/go:1.16-alpine3.13 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
|
||||
@@ -335,6 +335,10 @@ func runChangePassword(c *cli.Context) error {
|
||||
if err := initDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(c.String("password")) < setting.MinPasswordLength {
|
||||
return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength)
|
||||
}
|
||||
|
||||
if !pwd.IsComplexEnough(c.String("password")) {
|
||||
return errors.New("Password does not meet complexity requirements")
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func (o outputType) String() string {
|
||||
}
|
||||
|
||||
var outputTypeEnum = &outputType{
|
||||
Enum: []string{"zip", "tar", "tar.gz", "tar.xz", "tar.bz2"},
|
||||
Enum: []string{"zip", "rar", "tar", "sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4"},
|
||||
Default: "zip",
|
||||
}
|
||||
|
||||
@@ -153,12 +153,16 @@ func fatal(format string, args ...interface{}) {
|
||||
func runDump(ctx *cli.Context) error {
|
||||
var file *os.File
|
||||
fileName := ctx.String("file")
|
||||
outType := ctx.String("type")
|
||||
if fileName == "-" {
|
||||
file = os.Stdout
|
||||
err := log.DelLogger("console")
|
||||
if err != nil {
|
||||
fatal("Deleting default logger failed. Can not write to stdout: %v", err)
|
||||
}
|
||||
} else {
|
||||
fileName = strings.TrimSuffix(fileName, path.Ext(fileName))
|
||||
fileName += "." + outType
|
||||
}
|
||||
setting.NewContext()
|
||||
// make sure we are logging to the console no matter what the configuration tells us do to
|
||||
@@ -197,7 +201,6 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
verbose := ctx.Bool("verbose")
|
||||
outType := ctx.String("type")
|
||||
var iface interface{}
|
||||
if fileName == "-" {
|
||||
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
||||
|
||||
@@ -18,9 +18,9 @@ params:
|
||||
description: Git with a cup of tea
|
||||
author: The Gitea Authors
|
||||
website: https://docs.gitea.io
|
||||
version: 1.14.6
|
||||
version: 1.15.8
|
||||
minGoVersion: 1.16
|
||||
goVersion: 1.16
|
||||
goVersion: 1.17
|
||||
minNodeVersion: 12.17
|
||||
|
||||
outputs:
|
||||
|
||||
2
go.mod
2
go.mod
@@ -9,7 +9,7 @@ require (
|
||||
gitea.com/go-chi/binding v0.0.0-20210301195521-1fe1c9a555e7
|
||||
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e
|
||||
gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e
|
||||
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee
|
||||
gitea.com/go-chi/session v0.0.0-20211218221615-e3605d8b28b8
|
||||
gitea.com/lunny/levelqueue v0.4.1
|
||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
|
||||
7
go.sum
7
go.sum
@@ -47,8 +47,8 @@ gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e h1:zgPGaf3kXP0cVm9J0l8
|
||||
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
|
||||
gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e h1:YjaQU6XFicdhPN+MlGolcXO8seYY2+EY5g7vZPB17CQ=
|
||||
gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e/go.mod h1:nfA7JaGv3hbGQ1ktdhAsZhdS84qKffI8NMlHr+Opsog=
|
||||
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee h1:9U6HuKUBt/cGK6T/64dEuz0r7Yp97WAAEJvXHDlY3ws=
|
||||
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee/go.mod h1:Ozg8IchVNb/Udg+ui39iHRYqVHSvf3C99ixdpLR8Vu0=
|
||||
gitea.com/go-chi/session v0.0.0-20211218221615-e3605d8b28b8 h1:tJQRXgZigkLeeW9LPlps9G9aMoE6LAmqigLA+wxmd1Q=
|
||||
gitea.com/go-chi/session v0.0.0-20211218221615-e3605d8b28b8/go.mod h1:fc/pjt5EqNKgqQXYzcas1Z5L5whkZHyOvTA7OzWVJck=
|
||||
gitea.com/lunny/levelqueue v0.4.1 h1:RZ+AFx5gBsZuyqCvofhAkPQ9uaVDPJnsULoJZIYaJNw=
|
||||
gitea.com/lunny/levelqueue v0.4.1/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
@@ -325,8 +325,9 @@ github.com/go-asn1-ber/asn1-ber v1.5.3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkPro
|
||||
github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k=
|
||||
github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs=
|
||||
github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg=
|
||||
github.com/go-chi/chi/v5 v5.0.1 h1:ALxjCrTf1aflOlkhMnCUP86MubbWFrzB3gkRPReLpTo=
|
||||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.0.4 h1:5e494iHzsYBiyXQAHHuI4tyJS9M3V84OuX3ufIIGHFo=
|
||||
github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
|
||||
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-enry/go-enry/v2 v2.7.1 h1:WCqtfyteIz61GYk9lRVy8HblvIv4cP9GIiwm/6txCbU=
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
3a810dbf6b96afaa8c5f69a8b6ec1dabfca7368b
|
||||
59e2c41e8f5140bb0182acebec17c8ad9831cc62
|
||||
|
||||
@@ -251,6 +251,26 @@ func prepareTestEnv(t testing.TB, skip ...int) func() {
|
||||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
|
||||
|
||||
assert.NoError(t, util.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
|
||||
ownerDirs, err := os.ReadDir(setting.RepoRootPath)
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, ownerDir := range ownerDirs {
|
||||
if !ownerDir.Type().IsDir() {
|
||||
continue
|
||||
}
|
||||
repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, repoDir := range repoDirs {
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0755)
|
||||
}
|
||||
}
|
||||
|
||||
return deferFn
|
||||
}
|
||||
|
||||
@@ -529,4 +549,23 @@ func resetFixtures(t *testing.T) {
|
||||
assert.NoError(t, models.LoadFixtures())
|
||||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
|
||||
assert.NoError(t, util.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
|
||||
ownerDirs, err := os.ReadDir(setting.RepoRootPath)
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, ownerDir := range ownerDirs {
|
||||
if !ownerDir.Type().IsDir() {
|
||||
continue
|
||||
}
|
||||
repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, repoDir := range repoDirs {
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0755)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ func TestLinksNoLogin(t *testing.T) {
|
||||
"/user/forgot_password",
|
||||
"/api/swagger",
|
||||
"/user2/repo1",
|
||||
"/user2/repo1/",
|
||||
"/user2/repo1/projects",
|
||||
"/user2/repo1/projects/1",
|
||||
"/assets/img/404.png",
|
||||
|
||||
@@ -61,6 +61,25 @@ func initMigrationTest(t *testing.T) func() {
|
||||
assert.True(t, len(setting.RepoRootPath) != 0)
|
||||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
|
||||
assert.NoError(t, util.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
|
||||
ownerDirs, err := os.ReadDir(setting.RepoRootPath)
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, ownerDir := range ownerDirs {
|
||||
if !ownerDir.Type().IsDir() {
|
||||
continue
|
||||
}
|
||||
repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, repoDir := range repoDirs {
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0755)
|
||||
}
|
||||
}
|
||||
|
||||
git.CheckLFSVersion()
|
||||
setting.InitDBConfig()
|
||||
|
||||
@@ -6,6 +6,7 @@ package integrations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
@@ -83,7 +84,7 @@ func TestNonasciiBranches(t *testing.T) {
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/Файл.md",
|
||||
to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
|
||||
to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
@@ -114,7 +115,7 @@ func TestNonasciiBranches(t *testing.T) {
|
||||
},
|
||||
{
|
||||
from: "タグ/ファイル.md",
|
||||
to: "tag/%e3%82%bf%e3%82%b0/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md",
|
||||
to: "tag/%e3%82%bf%e3%82%b0/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
// Files
|
||||
@@ -125,12 +126,12 @@ func TestNonasciiBranches(t *testing.T) {
|
||||
},
|
||||
{
|
||||
from: "Файл.md",
|
||||
to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
|
||||
to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "ファイル.md",
|
||||
to: "branch/Plus+Is+Not+Space/%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.md",
|
||||
to: "branch/Plus+Is+Not+Space/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.md",
|
||||
status: http.StatusNotFound, // it's not on default branch
|
||||
},
|
||||
// Same but url-encoded (few tests)
|
||||
@@ -146,7 +147,7 @@ func TestNonasciiBranches(t *testing.T) {
|
||||
},
|
||||
{
|
||||
from: "%D0%A4%D0%B0%D0%B9%D0%BB.md",
|
||||
to: "branch/Plus+Is+Not+Space/%d0%a4%d0%b0%d0%b9%d0%bb.md",
|
||||
to: "branch/Plus+Is+Not+Space/%D0%A4%D0%B0%D0%B9%D0%BB.md",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
@@ -159,6 +160,41 @@ func TestNonasciiBranches(t *testing.T) {
|
||||
to: "tag/%d0%81/%e4%ba%ba",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/%25%252525mightnotplaywell",
|
||||
to: "branch/Plus+Is+Not+Space/%25%252525mightnotplaywell",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/%25253Fisnotaquestion%25253F",
|
||||
to: "branch/Plus+Is+Not+Space/%25253Fisnotaquestion%25253F",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/" + url.PathEscape("%3Fis?and#afile"),
|
||||
to: "branch/Plus+Is+Not+Space/" + url.PathEscape("%3Fis?and#afile"),
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/10%25.md",
|
||||
to: "branch/Plus+Is+Not+Space/10%25.md",
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/" + url.PathEscape("This+file%20has 1space"),
|
||||
to: "branch/Plus+Is+Not+Space/" + url.PathEscape("This+file%20has 1space"),
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/" + url.PathEscape("This+file%2520has 2 spaces"),
|
||||
to: "branch/Plus+Is+Not+Space/" + url.PathEscape("This+file%2520has 2 spaces"),
|
||||
status: http.StatusOK,
|
||||
},
|
||||
{
|
||||
from: "Plus+Is+Not+Space/" + url.PathEscape("£15&$6.txt"),
|
||||
to: "branch/Plus+Is+Not+Space/" + url.PathEscape("£15&$6.txt"),
|
||||
status: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
defer prepareTestEnv(t)()
|
||||
|
||||
@@ -1,128 +1,81 @@
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
lQVYBF3190cBDADpfh1CvNtLl8N6lJQ03jymeE8h2ocvT61stAj31eefiOvZPDyx
|
||||
n0kRztBcrQ1OITBEslYqKiYHVfVptscIWf+5bARoHnLQIgpJEio00ggqO3AP8lIZ
|
||||
uiy9/ARDVgyPl3WgMza/J3Z7W0sBJTtN/6W35i+eNEY4Q0mScmNIVc75oo5ey/pL
|
||||
JSF0qumiy94o38dy6Vk2dPEf5LyxJWoA4dLvj49LL/QGPqnsAXAQXr1zULaRuwf2
|
||||
a8oKebr3m9wVkZcaH86duUmkU822k6OZSSxWCxZFFGVkC/VaA0uUjIL4a6SQqOOr
|
||||
PPOttmCLXJrtvpFdRwJ4PNwr9r2nPDDLwoajLJ8zo5jRumzwvkK9vALkY0BPuVoC
|
||||
qFdGY+2SGYKa4FTE7Mri/5j0NhWplhbcdGRe5doGDxJHbIN2UO21XjDlTBcscKep
|
||||
mWPVE2cdJrspYaZ9O0L6vhMVwGyyk+Qxmf6NbDw0q63AtqVe9qwbr2O3Irxseftw
|
||||
uWuSuLXzp+SMh/0AEQEAAQAL/2ExopuDwuNSHsh5bcIeGnAPV51Xentqtt2viaYk
|
||||
0AB8PfTVGsyzafa0OM7DKG0z6oRGGhD+L4tRMFGbiHlFAWqdeK4gsplJ+i8VlSUc
|
||||
otJ1oH262IsmEPban6mp+ZuSKCASAYGLu0m5JF0rMucSeli1RHAeAXbtJ4SDAin7
|
||||
sib/EDWMwjkikS0f8hZWt7kbAcqnMQA2qKKmlBdHZDtOxX/8KeFZ6kHpNtFrfcsK
|
||||
rOECIaVDDhr5HobCyl3E7tW5nrlrvSUkLVFl0IjcypqfzDlZp04PMdswhkdfBhu+
|
||||
0iY4K+d4uMPMzcpF1+mcn8C+7XK7jOqZysQa42bqgFHWEqljjJiUCuXfHbxnZWls
|
||||
0R2j9FLgTqtPQ33f3zMjhOyvdiy1DmfzU9MSu/I0VqCJnq6AwlW5rBQaKwAQuHMB
|
||||
UJ7bjMx/z41z41v0IFpxHnwSa+tkl49tV+y8zVtajfwXxJNy8j/ElX0ywfM5sDHa
|
||||
RAVwI7DSwMk5azp3F15DnA6XbwYA8O0b5AIeCo8edmIdKgY3vAi20j/lsTgsTUkY
|
||||
GTQ4BdMohr9gpZWHZZmQ1TeZokm4Auex7UgPblflufepkADassXixMmSNUsggGI+
|
||||
sR9qydNCw+qzgaJjchpwT5TdLJNHRbE+6VuGXJftcjdfXiKYZltEQBX8U4w7hui8
|
||||
D6dpzJK5mE1QebrFnJ7IKpAe+hWTc1+g9iHH3rInPMIzQW72WqSKndKIrRy1PZS5
|
||||
WM5MJzgWQaDzZSOQhrKA4yLIyzsrBgD4GfFLWh+sQ02sob5xmpDblfQUYVRy5TAx
|
||||
4WOLSflJqqyarrk7s1D7obqsSoAEdJk521dpE/0ciI5xT41fQKMXH1Qm9tu9uW5d
|
||||
1Y3oDxQXFJFa34gi5J9UbUBBIJRU0KyFcB1mGVF+fKbAKGPFR2lMCmkeqAYjVohM
|
||||
PG+tluArQrQYCwkZroR460TqvSadmPUekEjYsIzwlaOkJhGf7r40G5Djgyb2/LoC
|
||||
JY28zH7P9MXxIc7WAWuMJniUOqvslXcGAOkfZ1KVI61AIAvkEoRUpKwNSofs2PDQ
|
||||
1K5Q9DN0NK5UNAAr+Wn91mw/MBXqxdheq9wjmcsvx8OAhvw7O89QMuTviCTUQjSl
|
||||
Wzel6gpoZhpOgVb2RTxV7yVrp2fgYKkeUr7hiGhSxw78guF2jLgfBgb1ef+XKIMk
|
||||
5anUqKcsHHiouBQbcUCDyKBcVeIUKjAuh9ADpqn1v1oVshugnjpx32Oq1AW6Mn9e
|
||||
SmxBoR7YIvsy79P2IonjixEAjSp1chkGpNQTtBhnaXRlYSA8Z2l0ZWFAZmFrZS5s
|
||||
b2NhbD6JAdQEEwEKAD4WIQQ4G/p4KVUOUEVu5g5R68KXFICqDwUCXfX3RwIbAwUJ
|
||||
A8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRBR68KXFICqD/8/C/4wYdr1
|
||||
Q6fnXiAdBZPQDOHUjCSjH1d6tbVYaCz0ku8rK1uU0oTToKRSTXH9K59erHl//MEX
|
||||
Rte6loI22y3GFA8wAWzFKGwb6wDUr0SkH21espsp+plKUI/gHV8JyfWs0pLmy/C0
|
||||
tOr9XhdnQepFjpDAquWszSO0B70G32Tl82Tzbrho6+ePvU+2X0fYj1F8q/2bmegB
|
||||
lL1CcdVuivBqYglj6tzlurPXFq1QenJdssZNn0fizGiGfTY/7kgrvKHc4KN03i9d
|
||||
PUrPMQw7J59KSFNdkE3KYdedmEeWBVmrbfC8QBEO1zcTJN9wwV8fVv4qOhKN8yIO
|
||||
QLuhBZTeChtP3i2FCPHQqbeD2f0SG+yBbWu/OyfSC2YHcGyjbNV8D9upNg5eIJ34
|
||||
Sm5i0tGUYEdq9QQROacXn2/MhyJuJYbFrTcsHLsSiwygUXvHOqi0G0gEjWl67yMd
|
||||
9YIq1sZlNs3WY7ASrV+QcB7B9WKJAyh5YWz/G4MlThU91YUfltAb3QmNFeadBVgE
|
||||
XfX3RwEMALH7pae22J/BmhFFBCjMld166hTknXjOR459csv5ppky91Yl82VFFg+J
|
||||
G6hbkGzvCQ5XDJu8xgWeXowe2sXkyDwhTRaB6MEnA4KW5PUazL7KlDGsR5oPvBlE
|
||||
dSQDGzTV/RPcszSNdcN9MRNbfAf0ZFV6D9R3CIlNZAm6HwML7lZ0JmCiLORz3TbF
|
||||
4kg1KDZIQAhY7Y7AuMdoXfnpUqFLba2ZxZBvdcrMcuYz8GkmFsYdi1/JuXEK3//B
|
||||
Mo7Pg78zsq7UolUcT2p3qKb7hB3CEtwa3xffwzgAcFSKYrCE/5/IYjHhS97uKWor
|
||||
8dh59wUCuPCmAiuIz3aD84rxZIHgBGPy03TEWCrCBCVxAdH/2Ezpn3DpuZyCuanJ
|
||||
0WGSzrPBw+twA8bk9BATvFVQ/7Bs9deSsMAOI1uj9lTy1R9LU/KHEr8BEz61+Bgk
|
||||
+m4ev6OQAVDY6QpRtf+zfB2xO95Wu4l1pIFuz7OJaZLCm2ApeAKsCCUDdTSJn5e7
|
||||
0i1E4SIVgwARAQABAAv/WHaZqbiqBw21RCwnmxfEzWbQfj37PxZYXqxfqJ6XfcHl
|
||||
Sb5nMcia5HHje1S3fk15FNWTgLzdN+G1YLPdTUsfczOiGzPKumZnyjqx5lnBtnr+
|
||||
GYpltF9pwK1UA+g/V42c0oh50f8Vr2rEP7jS9ykzzYBz6ciYR5ZdyK/nxh3iArqM
|
||||
cK9q3MnyA81rYTR6njBfE0cQHEoSDZsESrj7xwu0ofqyRc4AoCHqYh0iu0ChRSte
|
||||
IOgk8djT6Uzfkjf2ZcyNiD2/iFzAXaI8CpoiiRJDn/qIhtSFqjb284wwbmTUE+Nw
|
||||
LjeMbpKQiWqnsw2GKhlXVvTLjrCb8TIKjbLtFH2HlEaIjL332GcVqkVy2TMtjZRi
|
||||
lhy/uSY2kzkBkoGJXp5isJFk3ZcOHHsG4VQ+08vq++GoqQE8U1t8zMfAbBFoFlpP
|
||||
nkRjZs0MwY9u6C0IiXRDrYrMIW12LjsRBiebGHUhzv10/4T0XZ8FKTewxcszcuMf
|
||||
lpbIotF1ItGqCXqgufnhBgDBhi8BErxO59ksWLAHdozDyiXwQ5ua6WesGrIRvw23
|
||||
Z8a5wxTByXmd1fMgJ509hpXbxUC94TGObJoUo23YE3TpqlTLs5NqeFzzU+OjWSb0
|
||||
Wo1hpFlzyatuynpz2aXbKbjw5dgyeIxj9t+NhGo2SW6v+RHtYAWJRFBFOPVOLwTy
|
||||
an733pA3MSUT0oEh+aggDkXEJLBum0P3Onnma7wR7Xj2Nk1SGLCMgVmKbtGlvyrj
|
||||
yc5FZhzuvOfeuLSYoa0KE4sGAOtxED2jDkV2HS67bxrUzMLvAAhOnRmunA7Qk4F7
|
||||
B2uMYa03O7vnUJAINpmZVu/ubWz1/JRV6M3/1lQTH+2B9kZ5v6kHrczCsoSP2dXD
|
||||
7CQnxSm6zngdgwkoo+9pgFztGUZM071SjRW+r1IwE/XBZNwFya5PM02/Akb0ejuB
|
||||
6K2ClnIFf7gflndUZ0mhZn48I88b6mzEG4X4uUZG+4vW8EZEInl+nMA9f3S6YT0U
|
||||
ZG4JC8JMKsmoYLye/BuedHxk6QX6AnMFBjK7cnfBnViJkmXhDLxmcCjwjUUBraRI
|
||||
QbyzHzY2Jq1VyhTJ1HZxE+vj26MzFFzjpe84r1Ggrcowx53RHstBBYBA5OjRy+cN
|
||||
vDzqqWz4cDKU/XlwJhRnG+PcY3c47obpvjjagcwG7xU4df15fDetKajnIloA5r22
|
||||
hbmVmTAqljyWLnvSNYrvf5QDqqg6tBuHITUiZhYgECpIoeEj9hU8MZSvQOscK0kx
|
||||
Vn8SqUjxDcNazQM8NoxNB10wfJw63hCJAbwEGAEKACYWIQQ4G/p4KVUOUEVu5g5R
|
||||
68KXFICqDwUCXfX3RwIbDAUJA8JnAAAKCRBR68KXFICqD54+DAC4VZpKrU6Oo04z
|
||||
/gJeC+3fNon6W9Pdxx7KimDOttkpCiss8JydO6aSB97xrWdvMBTui333qGo2exE/
|
||||
XFA4RF7K4lAKUWbwaR1brLQfGVYOltmMb986/LeE3OsmMt4vbxUnGvHVX+QXDWAr
|
||||
p6q4DZvMgQQhbWp+rMjXtRr10iQnSlM5CYhyawdiiahFqgoo8395l/2JA2YGhUgU
|
||||
nARUPZ9SqaUmRm+KGsSyoYnvN9apiDk5KVQoyfrmweNN7DCIIcoh/B9Ax8nmouKz
|
||||
yBB2fjCM/bJNtN/AsgYbZIScuYK/xqTkwNtbe5WdCyD/QJOHTsPJzx59hgSVo6gf
|
||||
Fe8VBnxHtrY8gPSUU3gkhYLvLzyVX+YLNzRcffobd8gJbfumwFJUkz91oGvYz7xg
|
||||
XN2qmsgBNCbTIzWZMpRDMAbY+n2QFImGf+EJZlMdj6gOrIYq8N4+nMW1FwJivsOb
|
||||
muqySyjZnD2AYjEA6OYPXfCVhaB5fTfhQXbIrZbgsEh4ob/eIdOdBVgEXta5egEM
|
||||
AMYlmZ47NqBMBeaN0o/ahYMe8eIMaroWkufMfC9VRBSMAkpbDl34oNp0cflmnMYo
|
||||
AFAl8ucRMFTiUnjiWpo27q14tjSyDVsn/CqwbnrgJgCFNV/MGsYsToEkb4JwDIRC
|
||||
bky+1BvqvI8RMlO3MlwzrlIaMrlQfx5NtUb9TyO7S4xZTz864+Ty5p3HhRwbdZMe
|
||||
Ko8sfXFhCcCHFXosI0mX83EyzsrXlbkGRawId7jvrdOAUg/cYP8f/XmV6z1NHHH9
|
||||
cvz+3oLOGuVxUdG0KuS/jigHrLWdRuKM3xfEeesp870yZU3AbyFdoHnGXROJePTl
|
||||
FV8j2P5Ahf/yuVhjdyJSKdZC2h6+HtLG9RiGgLviLLYhtlZG2H6pYyKY5Ud3php+
|
||||
qw1aYL1xtdxrHYkQlAa0vLY/mwpuPfMke9I+rtnrwlLRMCstdiN34ybZ4sRD+gL1
|
||||
w5VIZ/aM6/Gsczd3s/T8psIi09TKPfEU2gWLMGvlDsgz+aSDdVP7XYQpNglaEPet
|
||||
PwARAQABAAv8CHg6+hnV2pblTwGTlTU7V8DO3gwMfn/QhQ/8ju66G5a7J6p/ZreQ
|
||||
nfCJnqYq4AgoW0SuqVSBbbTENF6YjixNmiSlb9iHMZ+ilms24xG0Y3lOMBYYCY3Y
|
||||
nTSNf6nXyconz31TW7jLmTdG9hpykKEKO9WFgt5UpgWe+2CAgtUoBDZyaLrVBZ2h
|
||||
te99WmziDbPQZeZPm7UQ0aX0iRBclxy4+dxjcnrcmi1mdQAM/glgs2sHbEjN7JnV
|
||||
dTOvUSN7/8ixj6I719Wx6MN6jE+BNd0ytZOun6tcDl0vamfT5fBpqbQoJMib2ggo
|
||||
+FGg9VFnzEMLqyI47LfOKUjCIhwVsxS4q9HXa2FtpO8UfRMPjDKgDZQzRTRJScrP
|
||||
s1NJ9HiM/eCHS1YjRmgroo60HygxkoLVCHp+Rz/hi0tG/ptv4q6mdnm8Mwb5JJtV
|
||||
48EvmZoNTWl9xOez1wmQn6caVHipc0qDqn/veoe8N5wdc+3hoMEXbSXqU+kx2KUa
|
||||
cVxCCVoUeURhBgDUGWtx34j1y17zE92BYhtVJTCU89dDe4wOEqGPyCGvRtgTmZ+1
|
||||
KwWr66pij91MV9mlY+7Ue2QHUSmgav2EFGIjVes956p4/F/CJ6qaYoekirMSnmX5
|
||||
jhRt4p6RW7m4omha3LAQ+gN4Fqa4acZUywENBvv1x3v+IWbjGJGn3eBnRrP3o9P+
|
||||
QUAtyMifiRm0ZN8J767o+bzUVmscXrkh7Qml47lQfDToyRI1UZZQmP2izpwHcwbZ
|
||||
NtfkgRUdeEq4GJUGAO8o4Oebbt0ALZ54E2LHhk8xi4ofKkFBDCkUFjcqS3bJJNck
|
||||
rkhfqEkMLETNhPbiC4TRNiunI5PXOinwNPkKI8P/hfp4S49WdIvnARazCoxjZNtl
|
||||
0Cbo+F1wtOH9FZaaWzNlU2lCQ2JJ3MCpLHz+nEmdYWOIWGQu2/s7smLODVEFbYKR
|
||||
50VWVRL7mB83v1XdfMFvExdQ7i5MOX4hFvmwi/WJIKClJfhNwTrHp6Jrm9jA66RL
|
||||
+dNyPKfwcFcYrqt1gwYAruZzP7QgTYVL+cmvGtCaHY4KoR8hanbpqR4YbzzyEXwS
|
||||
ll2FUCaVSokuRAdH3+/CHF9bqog3Zvn6HYcCS/A/rHVGIU9a+7s5IbRe0Ysc2FAN
|
||||
Nm9AsC5YnuyoAjW3cJGaZLYxp2WOZcMEXZeLPFYrNz22R1nRoxnUIPRpsKICXcK0
|
||||
aC4rSMk479jc/8WprWx4d45EVG+6Gsh1AT8LVhDL9yHFrh50ss2jCe1Fnftet6DI
|
||||
V5zHcxBx4sCs91aPxxe12UiJA2wEGAEKACAWIQQ4G/p4KVUOUEVu5g5R68KXFICq
|
||||
DwUCXta5egIbAgHACRBR68KXFICqD8D0IAQZAQoAHRYhBKAm5ShdO9gmF/o8jan0
|
||||
RkmWoKbKBQJe1rl6AAoJEKn0RkmWoKbKacUL/3YYKmiVvcr5LYFzMdwdahkla+6m
|
||||
hEEkL0l3dJNuU97Ou71tA1ieF0fjbVRSWjXKsntKwhyPoXjaZEZwMmv7iZ8BXV+b
|
||||
oO/EG5sg2/6iukJFXZqGnQwMdLVo1jPoXDteZU1qYiCoxLHhGhHL7ivtD1ygEi6w
|
||||
/cMbbOEB5Le1vOWIwqazs8dDcAYyy1PKthRl0ygvh8CpqPwy+AK3uLm0TVwetQAp
|
||||
taux0bDYWCb5Aft1r1nlV44gU4RiC131TDo+TKd754+UuI+UHk1D+LjTmZxRX2S6
|
||||
fXgoMXzrWmthGPdqvVOgKWm7Ef18hmaBECvPnp/tUJeDVVe02KrYQi8Bf2kxveSd
|
||||
8T0N/ExcydU9HgzTL8MuyPI+yp086elQzKJu6vb9tpgxCcglQZrUNT9Uy82pzTRY
|
||||
z9MmhnCDI2SD5L/CW5PsNpPTPy7s3f9DOV0G5Vka4LTSBOCK64NvAGBmRf8rFjJU
|
||||
lPtRPhC7h6uHdUIx3Q550Xogvq5sQm8UBCsbG8OJDADT3FJSIulR9Sh96OsES3sc
|
||||
H09juN4KcbpS03MAeUFwXqw3jBMhDoGKlsjX17Jf31qh/nI/XjigS3XWyj1BLSMG
|
||||
rJfH0NyYoGDCnff37tf+8lD9km9TlnV4Qjd9ujYbDRsefhaSjLVcy/gqdxZEuNBC
|
||||
BWmGwsmLI3nyZ4KDtNsa5JUHUNNZLBN20hvmE41Eszmz4Yg9Ho9DxKiFKvzUULMc
|
||||
bnMHaVHseHHq6+NVUnN1SAcOA0ygjnEid8D57RtdBCD90LXjLB7vlR+HaSMZYOnr
|
||||
DtseivHvqqy4+rxhwV2S3avnls9vRwE4bV6GCiqhoBnWIZRrARLZc2OTBIya82vS
|
||||
BIS1eyhjif1mE7Lqhs6aPD+eqQK2mBtQ/sidN8P/IfKfVF5siXfFbuGZLz5nRIho
|
||||
Yp1z7oO3OZ09lpUk0G1h+ouIFF6goDP48M/AKtbvs9OWk3QKxnOUZD8sRncq95x6
|
||||
m4q1MVb+aJyxwBqDRGaFY+3TVArB1b+kG1JsAvV5dag=
|
||||
=511T
|
||||
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
|
||||
ZMtt+nu5oJo/m1bvhWiYLhW6WX8TcmRKD3s=
|
||||
=V9rS
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestSignOut(t *testing.T) {
|
||||
session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
// try to view a private repo, should fail
|
||||
req = NewRequest(t, "GET", "/user2/repo2/")
|
||||
req = NewRequest(t, "GET", "/user2/repo2")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
// invalidate cached cookies for user2, for subsequent tests
|
||||
|
||||
@@ -1145,17 +1145,17 @@ type IssuesOptions struct {
|
||||
func sortIssuesSession(sess *xorm.Session, sortType string, priorityRepoID int64) {
|
||||
switch sortType {
|
||||
case "oldest":
|
||||
sess.Asc("issue.created_unix")
|
||||
sess.Asc("issue.created_unix").Asc("issue.id")
|
||||
case "recentupdate":
|
||||
sess.Desc("issue.updated_unix")
|
||||
sess.Desc("issue.updated_unix").Desc("issue.created_unix").Desc("issue.id")
|
||||
case "leastupdate":
|
||||
sess.Asc("issue.updated_unix")
|
||||
sess.Asc("issue.updated_unix").Asc("issue.created_unix").Asc("issue.id")
|
||||
case "mostcomment":
|
||||
sess.Desc("issue.num_comments")
|
||||
sess.Desc("issue.num_comments").Desc("issue.created_unix").Desc("issue.id")
|
||||
case "leastcomment":
|
||||
sess.Asc("issue.num_comments")
|
||||
sess.Asc("issue.num_comments").Desc("issue.created_unix").Desc("issue.id")
|
||||
case "priority":
|
||||
sess.Desc("issue.priority")
|
||||
sess.Desc("issue.priority").Desc("issue.created_unix").Desc("issue.id")
|
||||
case "nearduedate":
|
||||
// 253370764800 is 01/01/9999 @ 12:00am (UTC)
|
||||
sess.Join("LEFT", "milestone", "issue.milestone_id = milestone.id").
|
||||
@@ -1163,17 +1163,25 @@ func sortIssuesSession(sess *xorm.Session, sortType string, priorityRepoID int64
|
||||
"WHEN issue.deadline_unix = 0 AND (milestone.deadline_unix = 0 OR milestone.deadline_unix IS NULL) THEN 253370764800 " +
|
||||
"WHEN milestone.deadline_unix = 0 OR milestone.deadline_unix IS NULL THEN issue.deadline_unix " +
|
||||
"WHEN milestone.deadline_unix < issue.deadline_unix OR issue.deadline_unix = 0 THEN milestone.deadline_unix " +
|
||||
"ELSE issue.deadline_unix END ASC")
|
||||
"ELSE issue.deadline_unix END ASC").
|
||||
Desc("issue.created_unix").
|
||||
Desc("issue.id")
|
||||
case "farduedate":
|
||||
sess.Join("LEFT", "milestone", "issue.milestone_id = milestone.id").
|
||||
OrderBy("CASE " +
|
||||
"WHEN milestone.deadline_unix IS NULL THEN issue.deadline_unix " +
|
||||
"WHEN milestone.deadline_unix < issue.deadline_unix OR issue.deadline_unix = 0 THEN milestone.deadline_unix " +
|
||||
"ELSE issue.deadline_unix END DESC")
|
||||
"ELSE issue.deadline_unix END DESC").
|
||||
Desc("issue.created_unix").
|
||||
Desc("issue.id")
|
||||
case "priorityrepo":
|
||||
sess.OrderBy("CASE WHEN issue.repo_id = " + strconv.FormatInt(priorityRepoID, 10) + " THEN 1 ELSE 2 END, issue.created_unix DESC")
|
||||
sess.OrderBy("CASE " +
|
||||
"WHEN issue.repo_id = " + strconv.FormatInt(priorityRepoID, 10) + " THEN 1 " +
|
||||
"ELSE 2 END ASC").
|
||||
Desc("issue.created_unix").
|
||||
Desc("issue.id")
|
||||
default:
|
||||
sess.Desc("issue.created_unix")
|
||||
sess.Desc("issue.created_unix").Desc("issue.id")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,25 @@ func prepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.En
|
||||
|
||||
assert.NoError(t, com.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"),
|
||||
setting.RepoRootPath))
|
||||
ownerDirs, err := os.ReadDir(setting.RepoRootPath)
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, ownerDir := range ownerDirs {
|
||||
if !ownerDir.Type().IsDir() {
|
||||
continue
|
||||
}
|
||||
repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
|
||||
if err != nil {
|
||||
assert.NoError(t, err, "unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, repoDir := range repoDirs {
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0755)
|
||||
}
|
||||
}
|
||||
|
||||
if err := deleteDB(); err != nil {
|
||||
t.Errorf("unable to reset database: %v", err)
|
||||
|
||||
@@ -21,13 +21,18 @@ func (repo *Repository) CanEnableTimetracker() bool {
|
||||
|
||||
// IsTimetrackerEnabled returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs.
|
||||
func (repo *Repository) IsTimetrackerEnabled() bool {
|
||||
return repo.isTimetrackerEnabled(x)
|
||||
}
|
||||
|
||||
// IsTimetrackerEnabled returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs.
|
||||
func (repo *Repository) isTimetrackerEnabled(e Engine) bool {
|
||||
if !setting.Service.EnableTimetracking {
|
||||
return false
|
||||
}
|
||||
|
||||
var u *RepoUnit
|
||||
var err error
|
||||
if u, err = repo.GetUnit(UnitTypeIssues); err != nil {
|
||||
if u, err = repo.getUnit(e, UnitTypeIssues); err != nil {
|
||||
return setting.Service.DefaultEnableTimetracking
|
||||
}
|
||||
return u.IssuesConfig().EnableTimetracker
|
||||
|
||||
@@ -87,6 +87,26 @@ func MainTest(m *testing.M, pathToGiteaRoot string) {
|
||||
fatalTestError("util.CopyDir: %v\n", err)
|
||||
}
|
||||
|
||||
ownerDirs, err := os.ReadDir(setting.RepoRootPath)
|
||||
if err != nil {
|
||||
fatalTestError("unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, ownerDir := range ownerDirs {
|
||||
if !ownerDir.Type().IsDir() {
|
||||
continue
|
||||
}
|
||||
repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
|
||||
if err != nil {
|
||||
fatalTestError("unable to read the new repo root: %v\n", err)
|
||||
}
|
||||
for _, repoDir := range repoDirs {
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0755)
|
||||
}
|
||||
}
|
||||
|
||||
exitStatus := m.Run()
|
||||
if err = util.RemoveAll(setting.RepoRootPath); err != nil {
|
||||
fatalTestError("util.RemoveAll: %v\n", err)
|
||||
@@ -128,6 +148,23 @@ func PrepareTestEnv(t testing.TB) {
|
||||
assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
|
||||
metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta")
|
||||
assert.NoError(t, util.CopyDir(metaPath, setting.RepoRootPath))
|
||||
|
||||
ownerDirs, err := os.ReadDir(setting.RepoRootPath)
|
||||
assert.NoError(t, err)
|
||||
for _, ownerDir := range ownerDirs {
|
||||
if !ownerDir.Type().IsDir() {
|
||||
continue
|
||||
}
|
||||
repoDirs, err := os.ReadDir(filepath.Join(setting.RepoRootPath, ownerDir.Name()))
|
||||
assert.NoError(t, err)
|
||||
for _, repoDir := range repoDirs {
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "pack"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0755)
|
||||
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0755)
|
||||
}
|
||||
}
|
||||
|
||||
base.SetupGiteaRoot() // Makes sure GITEA_ROOT is set
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +223,9 @@ func APIAuth(authMethod auth.Auth) func(*APIContext) {
|
||||
// Get user from session if logged in.
|
||||
ctx.User = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session)
|
||||
if ctx.User != nil {
|
||||
if ctx.Locale.Language() != ctx.User.Language {
|
||||
ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
|
||||
}
|
||||
ctx.IsBasicAuth = ctx.Data["AuthedMethod"].(string) == new(auth.Basic).Name()
|
||||
ctx.IsSigned = true
|
||||
ctx.Data["IsSigned"] = ctx.IsSigned
|
||||
|
||||
@@ -642,6 +642,9 @@ func Auth(authMethod auth.Auth) func(*Context) {
|
||||
return func(ctx *Context) {
|
||||
ctx.User = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session)
|
||||
if ctx.User != nil {
|
||||
if ctx.Locale.Language() != ctx.User.Language {
|
||||
ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
|
||||
}
|
||||
ctx.IsBasicAuth = ctx.Data["AuthedMethod"].(string) == new(auth.Basic).Name()
|
||||
ctx.IsSigned = true
|
||||
ctx.Data["IsSigned"] = ctx.IsSigned
|
||||
@@ -669,6 +672,7 @@ func Contexter() func(next http.Handler) http.Handler {
|
||||
var locale = middleware.Locale(resp, req)
|
||||
var startTime = time.Now()
|
||||
var link = setting.AppSubURL + strings.TrimSuffix(req.URL.EscapedPath(), "/")
|
||||
|
||||
var ctx = Context{
|
||||
Resp: NewResponse(resp),
|
||||
Cache: mc.GetCache(),
|
||||
|
||||
@@ -833,7 +833,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
setting.AppSubURL,
|
||||
strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*")),
|
||||
ctx.Repo.BranchNameSubURL(),
|
||||
ctx.Repo.TreePath))
|
||||
util.PathEscapeSegments(ctx.Repo.TreePath)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,13 +159,13 @@ func checkDBConsistency(logger log.Logger, autofix bool) error {
|
||||
"lfs_lock", "repository", "lfs_lock.repo_id=repository.id"),
|
||||
// find collaborations without users
|
||||
genericOrphanCheck("Collaborations without existing user",
|
||||
"collaboration", "user", "collaboration.user_id=user.id"),
|
||||
"collaboration", "user", "collaboration.user_id=`user`.id"),
|
||||
// find collaborations without repository
|
||||
genericOrphanCheck("Collaborations without existing repository",
|
||||
"collaboration", "repository", "collaboration.repo_id=repository.id"),
|
||||
// find access without users
|
||||
genericOrphanCheck("Access entries without existing user",
|
||||
"access", "user", "access.user_id=user.id"),
|
||||
"access", "user", "access.user_id=`user`.id"),
|
||||
// find access without repository
|
||||
genericOrphanCheck("Access entries without existing repository",
|
||||
"access", "repository", "access.repo_id=repository.id"),
|
||||
|
||||
@@ -27,6 +27,20 @@ type WriteCloserError interface {
|
||||
CloseWithError(err error) error
|
||||
}
|
||||
|
||||
// EnsureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
|
||||
// Run before opening git cat-file.
|
||||
// This is needed otherwise the git cat-file will hang for invalid repositories.
|
||||
func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
|
||||
stderr := strings.Builder{}
|
||||
err := NewCommandContext(ctx, "rev-parse").
|
||||
SetDescription(fmt.Sprintf("%s rev-parse [repo_path: %s]", GitExecutable, repoPath)).
|
||||
RunInDirFullPipeline(repoPath, nil, &stderr, nil)
|
||||
if err != nil {
|
||||
return ConcatenateError(err, (&stderr).String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CatFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
|
||||
func CatFileBatchCheck(repoPath string) (WriteCloserError, *bufio.Reader, func()) {
|
||||
batchStdinReader, batchStdinWriter := io.Pipe()
|
||||
|
||||
@@ -218,6 +218,8 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi
|
||||
} else {
|
||||
otherLine++
|
||||
}
|
||||
case '\\':
|
||||
// FIXME: handle `\ No newline at end of file`
|
||||
default:
|
||||
currentLine++
|
||||
otherLine++
|
||||
|
||||
@@ -42,6 +42,57 @@ index d8e4c92..19dc8ad 100644
|
||||
/
|
||||
`
|
||||
|
||||
var issue17875Diff = `diff --git a/Geschäftsordnung.md b/Geschäftsordnung.md
|
||||
index d46c152..a7d2d55 100644
|
||||
--- a/Geschäftsordnung.md
|
||||
+++ b/Geschäftsordnung.md
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
-date: "23.01.2021"
|
||||
+date: "30.11.2021"
|
||||
...
|
||||
` + `
|
||||
# Geschäftsordnung
|
||||
@@ -16,4 +16,22 @@ Diese Geschäftsordnung regelt alle Prozesse des Vereins, solange diese nicht du
|
||||
` + `
|
||||
## § 3 Datenschutzverantwortlichkeit
|
||||
` + `
|
||||
-1. Der Verein bestellt eine datenschutzverantwortliche Person mit den Aufgaben nach Artikel 39 DSGVO.
|
||||
\ No newline at end of file
|
||||
+1. Der Verein bestellt eine datenschutzverantwortliche Person mit den Aufgaben nach Artikel 39 DSGVO.
|
||||
+
|
||||
+## §4 Umgang mit der SARS-Cov-2-Pandemie
|
||||
+
|
||||
+1. Der Vorstand hat die Befugnis, in Rücksprache mit den Vereinsmitgliedern, verschiedene Hygienemaßnahmen für Präsenzveranstaltungen zu beschließen.
|
||||
+
|
||||
+2. Die Einführung, Änderung und Abschaffung dieser Maßnahmen sind nur zum Zweck der Eindämmung der SARS-Cov-2-Pandemie zulässig.
|
||||
+
|
||||
+3. Die Einführung, Änderung und Abschaffung von Maßnahmen nach Abs. 2 bedarf einer wissenschaftlichen Grundlage.
|
||||
+
|
||||
+4. Die Maßnahmen nach Abs. 2 setzen sich aus den folgenden Bausteinen inklusive einer ihrer Ausprägungen zusammen.
|
||||
+
|
||||
+ 1. Maskenpflicht: Keine; Maskenpflicht, außer am Platz, oder wo Abstände nicht eingehalten werden können; Maskenpflicht, wenn Abstände nicht eingehalten werden können; Maskenpflicht
|
||||
+
|
||||
+ 2. Geimpft-, Genesen- oder Testnachweis: Kein Nachweis notwendig; Nachweis, dass Person geimpft, genesen oder tagesaktuell getestet ist (3G); Nachweis, dass Person geimpft oder genesen ist (2G); Nachweis, dass Person geimpft bzw. genesen und tagesaktuell getestet ist (2G+)
|
||||
+
|
||||
+ 3. Online-Veranstaltung: Keine, parallele Online-Veranstaltung, ausschließlich Online-Veranstaltung
|
||||
+
|
||||
+5. Bei Präsenzveranstungen gelten außerdem die Hygienevorschriften des Veranstaltungsorts. Bei Regelkollision greift die restriktivere Regel.
|
||||
\ No newline at end of file`
|
||||
|
||||
func TestCutDiffAroundLineIssue17875(t *testing.T) {
|
||||
result, err := CutDiffAroundLine(strings.NewReader(issue17875Diff), 23, false, 3)
|
||||
assert.NoError(t, err)
|
||||
expected := `diff --git a/Geschäftsordnung.md b/Geschäftsordnung.md
|
||||
--- a/Geschäftsordnung.md
|
||||
+++ b/Geschäftsordnung.md
|
||||
@@ -20,0 +21,3 @@
|
||||
+## §4 Umgang mit der SARS-Cov-2-Pandemie
|
||||
+
|
||||
+1. Der Vorstand hat die Befugnis, in Rücksprache mit den Vereinsmitgliedern, verschiedene Hygienemaßnahmen für Präsenzveranstaltungen zu beschließen.`
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
|
||||
func TestCutDiffAroundLine(t *testing.T) {
|
||||
result, err := CutDiffAroundLine(strings.NewReader(exampleDiff), 4, false, 3)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -43,6 +43,11 @@ func OpenRepository(repoPath string) (*Repository, error) {
|
||||
return nil, errors.New("no such file or directory")
|
||||
}
|
||||
|
||||
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
||||
if err := EnsureValidGitRepository(DefaultContext, repoPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repo := &Repository{
|
||||
Path: repoPath,
|
||||
tagCache: newObjectCache(),
|
||||
|
||||
@@ -38,7 +38,10 @@ func (repo *Repository) ResolveReference(name string) (string, error) {
|
||||
func (repo *Repository) GetRefCommitID(name string) (string, error) {
|
||||
wr, rd, cancel := repo.CatFileBatchCheck()
|
||||
defer cancel()
|
||||
_, _ = wr.Write([]byte(name + "\n"))
|
||||
_, err := wr.Write([]byte(name + "\n"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
shaBs, _, _, err := ReadBatchLine(rd)
|
||||
if IsErrNotExist(err) {
|
||||
return "", ErrNotExist{name, ""}
|
||||
|
||||
@@ -276,6 +276,12 @@ func (b *BleveIndexer) Index(repo *models.Repository, sha string, changes *repoC
|
||||
batch := gitea_bleve.NewFlushingBatch(b.indexer, maxBatchSize)
|
||||
if len(changes.Updates) > 0 {
|
||||
|
||||
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
||||
if err := git.EnsureValidGitRepository(git.DefaultContext, repo.RepoPath()); err != nil {
|
||||
log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err)
|
||||
return err
|
||||
}
|
||||
|
||||
batchWriter, batchReader, cancel := git.CatFileBatch(repo.RepoPath())
|
||||
defer cancel()
|
||||
|
||||
|
||||
@@ -248,6 +248,11 @@ func (b *ElasticSearchIndexer) addDelete(filename string, repo *models.Repositor
|
||||
func (b *ElasticSearchIndexer) Index(repo *models.Repository, sha string, changes *repoChanges) error {
|
||||
reqs := make([]elastic.BulkableRequest, 0)
|
||||
if len(changes.Updates) > 0 {
|
||||
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
||||
if err := git.EnsureValidGitRepository(git.DefaultContext, repo.RepoPath()); err != nil {
|
||||
log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err)
|
||||
return err
|
||||
}
|
||||
|
||||
batchWriter, batchReader, cancel := git.CatFileBatch(repo.RepoPath())
|
||||
defer cancel()
|
||||
|
||||
@@ -259,7 +259,7 @@ normalLoop:
|
||||
}
|
||||
|
||||
// Process naughty character
|
||||
if _, err := fmt.Fprintf(c.w, `\%#o03d`, bytes[i]); err != nil {
|
||||
if _, err := fmt.Fprintf(c.w, `\%#03o`, bytes[i]); err != nil {
|
||||
return totalWritten, err
|
||||
}
|
||||
i++
|
||||
|
||||
@@ -148,8 +148,6 @@ func (a *actionNotifier) NotifyNewPullRequest(pull *models.PullRequest, mentions
|
||||
}
|
||||
|
||||
func (a *actionNotifier) NotifyRenameRepository(doer *models.User, repo *models.Repository, oldRepoName string) {
|
||||
log.Trace("action.ChangeRepositoryName: %s/%s", doer.Name, repo.Name)
|
||||
|
||||
if err := models.NotifyWatchers(&models.Action{
|
||||
ActUserID: doer.ID,
|
||||
ActUser: doer,
|
||||
|
||||
@@ -4,9 +4,21 @@
|
||||
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gitea.com/go-chi/session"
|
||||
)
|
||||
|
||||
// Store represents a session store
|
||||
type Store interface {
|
||||
Get(interface{}) interface{}
|
||||
Set(interface{}, interface{}) error
|
||||
Delete(interface{}) error
|
||||
}
|
||||
|
||||
// RegenerateSession regenerates the underlying session and returns the new store
|
||||
func RegenerateSession(resp http.ResponseWriter, req *http.Request) (Store, error) {
|
||||
s, err := session.RegenerateSession(resp, req)
|
||||
return s, err
|
||||
}
|
||||
|
||||
@@ -58,6 +58,9 @@ func runMigrateTask(t *models.Task) (err error) {
|
||||
t.EndTime = timeutil.TimeStampNow()
|
||||
t.Status = structs.TaskStatusFailed
|
||||
t.Message = err.Error()
|
||||
// Ensure that the repo loaded before we zero out the repo ID from the task - thus ensuring that we can delete it
|
||||
_ = t.LoadRepo()
|
||||
|
||||
t.RepoID = 0
|
||||
if err := t.UpdateCols("status", "errors", "repo_id", "end_time"); err != nil {
|
||||
log.Error("Task UpdateCols failed: %v", err)
|
||||
|
||||
@@ -92,7 +92,7 @@ func CreateMigrateTask(doer, u *models.User, opts base.MigrateOptions) (*models.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var task = models.Task{
|
||||
var task = &models.Task{
|
||||
DoerID: doer.ID,
|
||||
OwnerID: u.ID,
|
||||
Type: structs.TaskTypeMigrateRepo,
|
||||
@@ -100,7 +100,7 @@ func CreateMigrateTask(doer, u *models.User, opts base.MigrateOptions) (*models.
|
||||
PayloadContent: string(bs),
|
||||
}
|
||||
|
||||
if err := models.CreateTask(&task); err != nil {
|
||||
if err := models.CreateTask(task); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -128,5 +128,5 @@ func CreateMigrateTask(doer, u *models.User, opts base.MigrateOptions) (*models.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &task, nil
|
||||
return task, nil
|
||||
}
|
||||
|
||||
@@ -31,7 +31,10 @@ func Open(uriStr string) (io.ReadCloser, error) {
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "http", "https":
|
||||
f, err := http.Get(uriStr)
|
||||
return f.Body, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f.Body, nil
|
||||
case "file":
|
||||
return os.Open(u.Path)
|
||||
default:
|
||||
|
||||
@@ -896,11 +896,12 @@ migrate.migrate = Migrate From %s
|
||||
migrate.migrating = Migrating from <b>%s</b> ...
|
||||
migrate.migrating_failed = Migrating from <b>%s</b> failed.
|
||||
migrate.migrating_failed.error = Error: %s
|
||||
migrate.github.description = Migrating data from Github.com or Github Enterprise.
|
||||
migrate.git.description = Migrating or Mirroring git data from Git services
|
||||
migrate.gitlab.description = Migrating data from GitLab.com or Self-Hosted gitlab server.
|
||||
migrate.gitea.description = Migrating data from Gitea.com or Self-Hosted Gitea server.
|
||||
migrate.gogs.description = Migrating data from notabug.org or other Self-Hosted Gogs server.
|
||||
migrate.github.description = Migrate data from github.com or other Github instances.
|
||||
migrate.git.description = Migrate a repository only from any Git service.
|
||||
migrate.gitlab.description = Migrate data from gitlab.com or other GitLab instances.
|
||||
migrate.gitea.description = Migrate data from gitea.com or other Gitea instances.
|
||||
migrate.gogs.description = Migrate data from notabug.org or other Gogs instances.
|
||||
migrate.onedev.description = Migrate data from code.onedev.io or other OneDev instances.
|
||||
migrate.migrating_git = Migrating Git Data
|
||||
migrate.migrating_topics = Migrating Topics
|
||||
migrate.migrating_milestones = Migrating Milestones
|
||||
|
||||
@@ -630,8 +630,8 @@ last_used=上次使用在
|
||||
no_activity=没有最近活动
|
||||
can_read_info=读取
|
||||
can_write_info=写入
|
||||
key_state_desc=7 天内使用过该密钥
|
||||
token_state_desc=7 天内使用过该密钥
|
||||
key_state_desc=7 天内使用过该密钥
|
||||
token_state_desc=7 天内使用过该密钥
|
||||
principal_state_desc=7 天内使用过该规则
|
||||
show_openid=在个人信息上显示
|
||||
hide_openid=在个人信息上隐藏
|
||||
@@ -808,7 +808,7 @@ watchers=关注者
|
||||
stargazers=称赞者
|
||||
forks=派生仓库
|
||||
pick_reaction=选择你的表情
|
||||
reactions_more=再加载 %d
|
||||
reactions_more=再加载 %d
|
||||
unit_disabled=站点管理员已禁用此仓库单元。
|
||||
language_other=其它
|
||||
adopt_search=输入用户名以搜索未被收录的仓库... (留空以查找全部)
|
||||
@@ -1611,7 +1611,7 @@ search=搜索
|
||||
search.search_repo=搜索仓库...
|
||||
search.fuzzy=模糊
|
||||
search.match=匹配
|
||||
search.results=在 <a href="%s"> %s </a> 中搜索 "%s" 的结果
|
||||
search.results=在 <a href="%[2]s"> %[3]s </a> 中搜索 "%[1]s" 的结果
|
||||
|
||||
settings=设置
|
||||
settings.desc=设置是你可以管理仓库设置的地方
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/convert"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/password"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/api/v1/user"
|
||||
@@ -167,6 +168,10 @@ func EditUser(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
if len(form.Password) != 0 {
|
||||
if len(form.Password) < setting.MinPasswordLength {
|
||||
ctx.Error(http.StatusBadRequest, "PasswordTooShort", fmt.Errorf("password must be at least %d characters", setting.MinPasswordLength))
|
||||
return
|
||||
}
|
||||
if !password.IsComplexEnough(form.Password) {
|
||||
err := errors.New("PasswordComplexity")
|
||||
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
|
||||
|
||||
@@ -87,7 +87,6 @@ import (
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
"gitea.com/go-chi/session"
|
||||
"github.com/go-chi/cors"
|
||||
)
|
||||
|
||||
@@ -547,20 +546,10 @@ func bind(obj interface{}) http.HandlerFunc {
|
||||
}
|
||||
|
||||
// Routes registers all v1 APIs routes to web application.
|
||||
func Routes() *web.Route {
|
||||
func Routes(sessioner func(next http.Handler) http.Handler) *web.Route {
|
||||
var m = web.NewRoute()
|
||||
|
||||
m.Use(session.Sessioner(session.Options{
|
||||
Provider: setting.SessionConfig.Provider,
|
||||
ProviderConfig: setting.SessionConfig.ProviderConfig,
|
||||
CookieName: setting.SessionConfig.CookieName,
|
||||
CookiePath: setting.SessionConfig.CookiePath,
|
||||
Gclifetime: setting.SessionConfig.Gclifetime,
|
||||
Maxlifetime: setting.SessionConfig.Maxlifetime,
|
||||
Secure: setting.SessionConfig.Secure,
|
||||
SameSite: setting.SessionConfig.SameSite,
|
||||
Domain: setting.SessionConfig.Domain,
|
||||
}))
|
||||
m.Use(sessioner)
|
||||
m.Use(securityHeaders())
|
||||
if setting.CORSConfig.Enabled {
|
||||
m.Use(cors.Handler(cors.Options{
|
||||
|
||||
@@ -96,6 +96,11 @@ func Transfer(ctx *context.APIContext) {
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Repo.GitRepo != nil {
|
||||
ctx.Repo.GitRepo.Close()
|
||||
ctx.Repo.GitRepo = nil
|
||||
}
|
||||
|
||||
if err := repo_service.StartRepositoryTransfer(ctx.User, newOwner, ctx.Repo.Repository, teams); err != nil {
|
||||
if models.IsErrRepoTransferInProgress(err) {
|
||||
ctx.Error(http.StatusConflict, "CreatePendingRepositoryTransfer", err)
|
||||
|
||||
@@ -22,6 +22,9 @@ func Middlewares() []func(http.Handler) http.Handler {
|
||||
var handlers = []func(http.Handler) http.Handler{
|
||||
func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
// First of all escape the URL RawPath to ensure that all routing is done using a correctly escaped URL
|
||||
req.URL.RawPath = req.URL.EscapedPath()
|
||||
|
||||
next.ServeHTTP(context.NewResponse(resp), req)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -40,6 +40,8 @@ import (
|
||||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
"code.gitea.io/gitea/services/repository"
|
||||
"code.gitea.io/gitea/services/webhook"
|
||||
|
||||
"gitea.com/go-chi/session"
|
||||
)
|
||||
|
||||
// NewServices init new services
|
||||
@@ -144,8 +146,20 @@ func NormalRoutes() *web.Route {
|
||||
r.Use(middle)
|
||||
}
|
||||
|
||||
r.Mount("/", web_routers.Routes())
|
||||
r.Mount("/api/v1", apiv1.Routes())
|
||||
sessioner := session.Sessioner(session.Options{
|
||||
Provider: setting.SessionConfig.Provider,
|
||||
ProviderConfig: setting.SessionConfig.ProviderConfig,
|
||||
CookieName: setting.SessionConfig.CookieName,
|
||||
CookiePath: setting.SessionConfig.CookiePath,
|
||||
Gclifetime: setting.SessionConfig.Gclifetime,
|
||||
Maxlifetime: setting.SessionConfig.Maxlifetime,
|
||||
Secure: setting.SessionConfig.Secure,
|
||||
SameSite: setting.SessionConfig.SameSite,
|
||||
Domain: setting.SessionConfig.Domain,
|
||||
})
|
||||
|
||||
r.Mount("/", web_routers.Routes(sessioner))
|
||||
r.Mount("/api/v1", apiv1.Routes(sessioner))
|
||||
r.Mount("/api/internal", private.Routes())
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func DeleteLabel(ctx *context.Context) {
|
||||
func InitializeLabels(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.InitializeLabelsForm)
|
||||
if ctx.HasError() {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/labels")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -319,6 +319,11 @@ func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
|
||||
}
|
||||
|
||||
if accept {
|
||||
if ctx.Repo.GitRepo != nil {
|
||||
ctx.Repo.GitRepo.Close()
|
||||
ctx.Repo.GitRepo = nil
|
||||
}
|
||||
|
||||
if err := repo_service.TransferOwnership(repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -619,6 +619,13 @@ func Home(ctx *context.Context) {
|
||||
if ctx.Repo.Repository.IsBeingCreated() {
|
||||
task, err := models.GetMigratingTask(ctx.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
if models.IsErrTaskDoesNotExist(err) {
|
||||
ctx.Data["Repo"] = ctx.Repo
|
||||
ctx.Data["CloneAddr"] = ""
|
||||
ctx.Data["Failed"] = true
|
||||
ctx.HTML(http.StatusOK, tplMigrating)
|
||||
return
|
||||
}
|
||||
ctx.ServerError("models.GetMigratingTask", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/password"
|
||||
"code.gitea.io/gitea/modules/recaptcha"
|
||||
"code.gitea.io/gitea/modules/session"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
@@ -87,6 +88,10 @@ func AutoSignIn(ctx *context.Context) (bool, error) {
|
||||
|
||||
isSucceed = true
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
return false, fmt.Errorf("unable to RegenerateSession: Error: %w", err)
|
||||
}
|
||||
|
||||
// Set session IDs
|
||||
if err := ctx.Session.Set("uid", u.ID); err != nil {
|
||||
return false, err
|
||||
@@ -98,10 +103,33 @@ func AutoSignIn(ctx *context.Context) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if err := resetLocale(ctx, u); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
middleware.DeleteCSRFCookie(ctx.Resp)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func resetLocale(ctx *context.Context, u *models.User) error {
|
||||
// Language setting of the user overwrites the one previously set
|
||||
// If the user does not have a locale set, we save the current one.
|
||||
if len(u.Language) == 0 {
|
||||
u.Language = ctx.Locale.Language()
|
||||
if err := models.UpdateUserCols(u, "language"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
middleware.SetLocaleCookie(ctx.Resp, u.Language, 0)
|
||||
|
||||
if ctx.Locale.Language() != u.Language {
|
||||
ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkAutoLogin(ctx *context.Context) bool {
|
||||
// Check auto-login.
|
||||
isSucceed, err := AutoSignIn(ctx)
|
||||
@@ -212,6 +240,11 @@ func SignInPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
ctx.ServerError("UserSignIn: Unable to set regenerate session", err)
|
||||
return
|
||||
}
|
||||
|
||||
// User needs to use 2FA, save data and redirect to 2FA page.
|
||||
if err := ctx.Session.Set("twofaUid", u.ID); err != nil {
|
||||
ctx.ServerError("UserSignIn: Unable to set twofaUid in session", err)
|
||||
@@ -372,6 +405,9 @@ func TwoFactorScratchPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
handleSignInFull(ctx, u, remember, false)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
ctx.Flash.Info(ctx.Tr("auth.twofa_scratch_used"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
return
|
||||
@@ -482,6 +518,9 @@ func U2FSign(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
redirect := handleSignInFull(ctx, user, remember, false)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
if redirect == "" {
|
||||
redirect = setting.AppSubURL + "/"
|
||||
}
|
||||
@@ -494,7 +533,11 @@ func U2FSign(ctx *context.Context) {
|
||||
|
||||
// This handles the final part of the sign-in process of the user.
|
||||
func handleSignIn(ctx *context.Context, u *models.User, remember bool) {
|
||||
handleSignInFull(ctx, u, remember, true)
|
||||
redirect := handleSignInFull(ctx, u, remember, true)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
ctx.Redirect(redirect)
|
||||
}
|
||||
|
||||
func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyRedirect bool) string {
|
||||
@@ -505,6 +548,12 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR
|
||||
setting.CookieRememberName, u.Name, days)
|
||||
}
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
ctx.ServerError("RegenerateSession", err)
|
||||
return setting.AppSubURL + "/"
|
||||
}
|
||||
|
||||
// Delete the openid, 2fa and linkaccount data
|
||||
_ = ctx.Session.Delete("openid_verified_uri")
|
||||
_ = ctx.Session.Delete("openid_signin_remember")
|
||||
_ = ctx.Session.Delete("openid_determined_email")
|
||||
@@ -528,13 +577,17 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR
|
||||
if len(u.Language) == 0 {
|
||||
u.Language = ctx.Locale.Language()
|
||||
if err := models.UpdateUserCols(u, "language"); err != nil {
|
||||
log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language))
|
||||
ctx.ServerError("UpdateUserCols Language", fmt.Errorf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language))
|
||||
return setting.AppSubURL + "/"
|
||||
}
|
||||
}
|
||||
|
||||
middleware.SetLocaleCookie(ctx.Resp, u.Language, 0)
|
||||
|
||||
if ctx.Locale.Language() != u.Language {
|
||||
ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
|
||||
}
|
||||
|
||||
// Clear whatever CSRF has right now, force to generate a new one
|
||||
middleware.DeleteCSRFCookie(ctx.Resp)
|
||||
|
||||
@@ -674,6 +727,11 @@ func getUserName(gothUser *goth.User) string {
|
||||
}
|
||||
|
||||
func showLinkingLogin(ctx *context.Context, gothUser goth.User) {
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
ctx.ServerError("RegenerateSession", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctx.Session.Set("linkAccountGothUser", gothUser); err != nil {
|
||||
log.Error("Error setting linkAccountGothUser in session: %v", err)
|
||||
}
|
||||
@@ -713,6 +771,11 @@ func handleOAuth2SignIn(ctx *context.Context, u *models.User, gothUser goth.User
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
ctx.ServerError("RegenerateSession", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctx.Session.Set("uid", u.ID); err != nil {
|
||||
log.Error("Error setting uid in session: %v", err)
|
||||
}
|
||||
@@ -738,6 +801,11 @@ func handleOAuth2SignIn(ctx *context.Context, u *models.User, gothUser goth.User
|
||||
log.Error("UpdateExternalUser failed: %v", err)
|
||||
}
|
||||
|
||||
if err := resetLocale(ctx, u); err != nil {
|
||||
ctx.ServerError("resetLocale", err)
|
||||
return
|
||||
}
|
||||
|
||||
if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 {
|
||||
middleware.DeleteRedirectToCookie(ctx.Resp)
|
||||
ctx.RedirectToFirst(redirectTo)
|
||||
@@ -748,6 +816,11 @@ func handleOAuth2SignIn(ctx *context.Context, u *models.User, gothUser goth.User
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
ctx.ServerError("RegenerateSession", err)
|
||||
return
|
||||
}
|
||||
|
||||
// User needs to use 2FA, save data and redirect to 2FA page.
|
||||
if err := ctx.Session.Set("twofaUid", u.ID); err != nil {
|
||||
log.Error("Error setting twofaUid in session: %v", err)
|
||||
@@ -937,6 +1010,11 @@ func linkAccount(ctx *context.Context, u *models.User, gothUser goth.User, remem
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
ctx.ServerError("RegenerateSession", err)
|
||||
return
|
||||
}
|
||||
|
||||
// User needs to use 2FA, save data and redirect to 2FA page.
|
||||
if err := ctx.Session.Set("twofaUid", u.ID); err != nil {
|
||||
log.Error("Error setting twofaUid in session: %v", err)
|
||||
@@ -1074,7 +1152,7 @@ func LinkAccountPostRegister(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/login")
|
||||
handleSignIn(ctx, u, false)
|
||||
}
|
||||
|
||||
// HandleSignOut resets the session and sets the cookies
|
||||
@@ -1216,7 +1294,7 @@ func SignUpPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("auth.sign_up_successful"))
|
||||
handleSignInFull(ctx, u, false, true)
|
||||
handleSignIn(ctx, u, false)
|
||||
}
|
||||
|
||||
// createAndHandleCreatedUser calls createUserInContext and
|
||||
@@ -1437,6 +1515,13 @@ func handleAccountActivation(ctx *context.Context, user *models.User) {
|
||||
|
||||
log.Trace("User activated: %s", user.Name)
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
log.Error("Unable to regenerate session for user: %-v with email: %s: %v", user, user.Email, err)
|
||||
ctx.ServerError("ActivateUserEmail", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Set session IDs
|
||||
if err := ctx.Session.Set("uid", user.ID); err != nil {
|
||||
log.Error("Error setting uid in session[%s]: %v", ctx.Session.ID(), err)
|
||||
}
|
||||
@@ -1447,6 +1532,11 @@ func handleAccountActivation(ctx *context.Context, user *models.User) {
|
||||
log.Error("Error storing session[%s]: %v", ctx.Session.ID(), err)
|
||||
}
|
||||
|
||||
if err := resetLocale(ctx, user); err != nil {
|
||||
ctx.ServerError("resetLocale", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("auth.account_activated"))
|
||||
ctx.Redirect(setting.AppSubURL + "/")
|
||||
}
|
||||
@@ -1704,11 +1794,14 @@ func ResetPasswdPost(ctx *context.Context) {
|
||||
|
||||
handleSignInFull(ctx, u, remember, false)
|
||||
ctx.Flash.Info(ctx.Tr("auth.twofa_scratch_used"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
return
|
||||
}
|
||||
|
||||
handleSignInFull(ctx, u, remember, true)
|
||||
handleSignIn(ctx, u, remember)
|
||||
}
|
||||
|
||||
// MustChangePassword renders the page to change a user's password
|
||||
@@ -1748,8 +1841,23 @@ func MustChangePasswordPost(ctx *context.Context) {
|
||||
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplMustChangePassword, &form)
|
||||
return
|
||||
}
|
||||
if !password.IsComplexEnough(form.Password) {
|
||||
ctx.Data["Err_Password"] = true
|
||||
ctx.RenderWithErr(password.BuildComplexityError(ctx), tplMustChangePassword, &form)
|
||||
return
|
||||
}
|
||||
pwned, err := password.IsPwned(ctx, form.Password)
|
||||
if pwned {
|
||||
ctx.Data["Err_Password"] = true
|
||||
errMsg := ctx.Tr("auth.password_pwned")
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
errMsg = ctx.Tr("auth.password_pwned_err")
|
||||
}
|
||||
ctx.RenderWithErr(errMsg, tplMustChangePassword, &form)
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
if err = u.SetPassword(form.Password); err != nil {
|
||||
ctx.ServerError("UpdateUser", err)
|
||||
return
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/hcaptcha"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/recaptcha"
|
||||
"code.gitea.io/gitea/modules/session"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
@@ -231,6 +232,11 @@ func signInOpenIDVerify(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
|
||||
ctx.ServerError("RegenerateSession", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctx.Session.Set("openid_verified_uri", id); err != nil {
|
||||
log.Error("signInOpenIDVerify: Could not set openid_verified_uri in session: %v", err)
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ func Action(ctx *context.Context) {
|
||||
}
|
||||
|
||||
var err error
|
||||
switch ctx.Params(":action") {
|
||||
switch ctx.Query("action") {
|
||||
case "follow":
|
||||
err = models.FollowUser(ctx.User.ID, u.ID)
|
||||
case "unfollow":
|
||||
@@ -329,7 +329,7 @@ func Action(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.Params(":action")), err)
|
||||
ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.Query("action")), err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package user
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
@@ -16,6 +17,12 @@ import (
|
||||
func TaskStatus(ctx *context.Context) {
|
||||
task, opts, err := models.GetMigratingTaskByID(ctx.ParamsInt64("task"), ctx.User.ID)
|
||||
if err != nil {
|
||||
if models.IsErrTaskDoesNotExist(err) {
|
||||
ctx.JSON(http.StatusNotFound, map[string]interface{}{
|
||||
"error": "task `" + strconv.FormatInt(ctx.ParamsInt64("task"), 10) + "` does not exist",
|
||||
})
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||
"err": err,
|
||||
})
|
||||
|
||||
@@ -39,7 +39,6 @@ import (
|
||||
_ "code.gitea.io/gitea/modules/session"
|
||||
|
||||
"gitea.com/go-chi/captcha"
|
||||
"gitea.com/go-chi/session"
|
||||
"github.com/NYTimes/gziphandler"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/cors"
|
||||
@@ -71,7 +70,7 @@ func CorsHandler() func(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
// Routes returns all web routes
|
||||
func Routes() *web.Route {
|
||||
func Routes(sessioner func(next http.Handler) http.Handler) *web.Route {
|
||||
routes := web.NewRoute()
|
||||
|
||||
routes.Use(public.AssetsHandler(&public.Options{
|
||||
@@ -80,17 +79,7 @@ func Routes() *web.Route {
|
||||
CorsHandler: CorsHandler(),
|
||||
}))
|
||||
|
||||
routes.Use(session.Sessioner(session.Options{
|
||||
Provider: setting.SessionConfig.Provider,
|
||||
ProviderConfig: setting.SessionConfig.ProviderConfig,
|
||||
CookieName: setting.SessionConfig.CookieName,
|
||||
CookiePath: setting.SessionConfig.CookiePath,
|
||||
Gclifetime: setting.SessionConfig.Gclifetime,
|
||||
Maxlifetime: setting.SessionConfig.Maxlifetime,
|
||||
Secure: setting.SessionConfig.Secure,
|
||||
SameSite: setting.SessionConfig.SameSite,
|
||||
Domain: setting.SessionConfig.Domain,
|
||||
}))
|
||||
routes.Use(sessioner)
|
||||
|
||||
routes.Use(Recovery())
|
||||
|
||||
@@ -461,9 +450,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Get("/attachments/{uuid}", repo.GetAttachment)
|
||||
}, ignSignIn)
|
||||
|
||||
m.Group("/{username}", func() {
|
||||
m.Post("/action/{action}", user.Action)
|
||||
}, reqSignIn)
|
||||
m.Post("/{username}", reqSignIn, user.Action)
|
||||
|
||||
if !setting.IsProd() {
|
||||
m.Get("/template/*", dev.TemplatePreview)
|
||||
@@ -1038,4 +1025,9 @@ func RegisterRoutes(m *web.Route) {
|
||||
if setting.API.EnableSwagger {
|
||||
m.Get("/swagger.v1.json", SwaggerV1Json)
|
||||
}
|
||||
m.NotFound(func(w http.ResponseWriter, req *http.Request) {
|
||||
ctx := context.GetContext(req)
|
||||
ctx.NotFound("", nil)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/session"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
)
|
||||
@@ -95,6 +96,14 @@ func isGitRawReleaseOrLFSPath(req *http.Request) bool {
|
||||
|
||||
// handleSignIn clears existing session variables and stores new ones for the specified user object
|
||||
func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore, user *models.User) {
|
||||
// We need to regenerate the session...
|
||||
newSess, err := session.RegenerateSession(resp, req)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Error regenerating session: %v", err))
|
||||
} else {
|
||||
sess = newSess
|
||||
}
|
||||
|
||||
_ = sess.Delete("openid_verified_uri")
|
||||
_ = sess.Delete("openid_signin_remember")
|
||||
_ = sess.Delete("openid_determined_email")
|
||||
@@ -103,7 +112,7 @@ func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore
|
||||
_ = sess.Delete("twofaRemember")
|
||||
_ = sess.Delete("u2fChallenge")
|
||||
_ = sess.Delete("linkAccount")
|
||||
err := sess.Set("uid", user.ID)
|
||||
err = sess.Set("uid", user.ID)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Error setting session: %v", err))
|
||||
}
|
||||
|
||||
@@ -713,7 +713,8 @@ func GetIssuesLastCommitStatus(issues models.IssueList) (map[int64]*models.Commi
|
||||
if !ok {
|
||||
gitRepo, err = git.OpenRepository(issue.Repo.RepoPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Error("Cannot open git repository %-v for issue #%d[%d]. Error: %v", issue.Repo, issue.Index, issue.ID, err)
|
||||
continue
|
||||
}
|
||||
gitRepos[issue.RepoID] = gitRepo
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/notification"
|
||||
"code.gitea.io/gitea/modules/sync"
|
||||
)
|
||||
@@ -53,6 +54,8 @@ func TransferOwnership(doer, newOwner *models.User, repo *models.Repository, tea
|
||||
|
||||
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
|
||||
func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoName string) error {
|
||||
log.Trace("ChangeRepositoryName: %s/%s -> %s", doer.Name, repo.Name, newRepoName)
|
||||
|
||||
oldRepoName := repo.Name
|
||||
|
||||
// Change repository directory name. We must lock the local copy of the
|
||||
@@ -66,6 +69,7 @@ func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoNam
|
||||
}
|
||||
repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
|
||||
|
||||
repo.Name = newRepoName
|
||||
notification.NotifyRenameRepository(doer, repo, oldRepoName)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<body>
|
||||
<p>{{.i18n.Tr "mail.hi_user_x" .DisplayName | Str2html}}</p><br>
|
||||
<p>{{.i18n.Tr "mail.reset_password.text" .ResetPwdCodeLives | Str2html}}</p><p><a href="{{$recover_url}}">{{$recover_url}}</a></p><br>
|
||||
<p>{{.i18n.Tr "mail.link_not_working_do_paste" .DisplayName AppName | Str2html}}</p>
|
||||
<p>{{.i18n.Tr "mail.link_not_working_do_paste"}}</p>
|
||||
|
||||
<p>© <a target="_blank" rel="noopener noreferrer" href="{{AppUrl}}">{{AppName}}</a></p>
|
||||
</body>
|
||||
|
||||
@@ -26,19 +26,16 @@
|
||||
|
||||
{{template "repo/migrate/options" .}}
|
||||
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div id="migrate_items">
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="migrate_items">
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
@@ -61,6 +58,13 @@
|
||||
<label>{{.i18n.Tr "repo.migrate_items_releases" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui divider"></div>
|
||||
|
||||
@@ -26,19 +26,15 @@
|
||||
|
||||
{{template "repo/migrate/options" .}}
|
||||
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div id="migrate_items">
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="migrate_items">
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
@@ -61,6 +57,13 @@
|
||||
<label>{{.i18n.Tr "repo.migrate_items_releases" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui divider"></div>
|
||||
|
||||
@@ -26,19 +26,15 @@
|
||||
|
||||
{{template "repo/migrate/options" .}}
|
||||
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div id="migrate_items">
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="migrate_items">
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
@@ -61,6 +57,13 @@
|
||||
<label>{{.i18n.Tr "repo.migrate_items_releases" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui divider"></div>
|
||||
|
||||
@@ -26,19 +26,16 @@
|
||||
|
||||
{{template "repo/migrate/options" .}}
|
||||
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div id="migrate_items">
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.migrate_items"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="wiki" type="checkbox" {{if .wiki}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="migrate_items">
|
||||
<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
@@ -50,6 +47,13 @@
|
||||
<label>{{.i18n.Tr "repo.migrate_items_issues" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
<div class="ui checkbox">
|
||||
<input name="milestones" type="checkbox" {{if .milestones}} checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Gogs do not support it
|
||||
<div class="inline field">
|
||||
<label></label>
|
||||
|
||||
@@ -25,7 +25,11 @@
|
||||
<p id="repo_migrating_progress_message"></p>
|
||||
</div>
|
||||
<div id="repo_migrating_failed" hidden>
|
||||
<p>{{.i18n.Tr "repo.migrate.migrating_failed" .CloneAddr | Safe}}</p>
|
||||
{{if .CloneAddr}}
|
||||
<p>{{.i18n.Tr "repo.migrate.migrating_failed" .CloneAddr | Safe}}</p>
|
||||
{{else}}
|
||||
<p>{{.i18n.Tr "repo.migrate.migrating_failed" "<nil>" | Safe}}</p>
|
||||
{{end}}
|
||||
<p id="repo_migrating_failed_error"></p>
|
||||
</div>
|
||||
{{if and .Failed .Permission.IsAdmin}}
|
||||
|
||||
@@ -66,12 +66,12 @@
|
||||
{{if and .IsSigned (ne .SignedUserName .Owner.Name)}}
|
||||
<li class="follow">
|
||||
{{if .SignedUser.IsFollowing .Owner.ID}}
|
||||
<form method="post" action="{{.Link}}/action/unfollow?redirect_to={{$.Link}}">
|
||||
<form method="post" action="{{.Link}}?action=unfollow&redirect_to={{$.Link}}">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<button type="submit" class="ui basic red button">{{svg "octicon-person"}} {{.i18n.Tr "user.unfollow"}}</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<form method="post" action="{{.Link}}/action/follow?redirect_to={{$.Link}}">
|
||||
<form method="post" action="{{.Link}}?action=follow&redirect_to={{$.Link}}">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<button type="submit" class="ui basic green button">{{svg "octicon-person"}} {{.i18n.Tr "user.follow"}}</button>
|
||||
</form>
|
||||
|
||||
6
vendor/gitea.com/go-chi/session/README.md
generated
vendored
6
vendor/gitea.com/go-chi/session/README.md
generated
vendored
@@ -1,6 +1,6 @@
|
||||
# Session
|
||||
|
||||
Middleware session provides session management which copied from [Macaron Session](https://gitea.com/go-chi/session) for [go-chi](https://github.com/go-chi/chi). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
|
||||
Middleware session provides session management which based on a [fork](https://gitea.com/macaron/session) of [Macaron Session](https://github.com/go-macaron/session) for [go-chi](https://github.com/go-chi/chi). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -10,8 +10,8 @@ go get gitea.com/go-chi/session
|
||||
|
||||
## Credits
|
||||
|
||||
This package is a modified version of [go-macaron/session](github.com/go-macaron/session).
|
||||
This package is a modified version of [go-macaron/session](https://github.com/go-macaron/session).
|
||||
|
||||
## License
|
||||
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
|
||||
|
||||
2
vendor/gitea.com/go-chi/session/go.mod
generated
vendored
2
vendor/gitea.com/go-chi/session/go.mod
generated
vendored
@@ -9,7 +9,7 @@ require (
|
||||
github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67 // indirect
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/go-chi/chi v1.5.1
|
||||
github.com/go-chi/chi/v5 v5.0.4
|
||||
github.com/go-redis/redis/v8 v8.4.0
|
||||
github.com/go-sql-driver/mysql v1.4.1
|
||||
github.com/lib/pq v1.2.0
|
||||
|
||||
12
vendor/gitea.com/go-chi/session/go.sum
generated
vendored
12
vendor/gitea.com/go-chi/session/go.sum
generated
vendored
@@ -10,7 +10,6 @@ github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67 h1:NCqJ6fwen6YP0
|
||||
github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 h1:Lgdd/Qp96Qj8jqLpq2cI1I1X7BJnu06efS+XkhRoLUQ=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -18,18 +17,16 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-chi/chi v1.5.1 h1:kfTK3Cxd/dkMu/rKs5ZceWYp+t5CtiE7vmaTv3LjC6w=
|
||||
github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k=
|
||||
github.com/go-chi/chi/v5 v5.0.4 h1:5e494iHzsYBiyXQAHHuI4tyJS9M3V84OuX3ufIIGHFo=
|
||||
github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-redis/redis/v8 v8.4.0 h1:J5NCReIgh3QgUJu398hUncxDExN4gMOHI11NVbVicGQ=
|
||||
github.com/go-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
@@ -48,7 +45,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
@@ -58,12 +54,10 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
@@ -118,7 +112,6 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -137,7 +130,6 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
|
||||
53
vendor/gitea.com/go-chi/session/session.go
generated
vendored
53
vendor/gitea.com/go-chi/session/session.go
generated
vendored
@@ -23,6 +23,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -259,7 +260,7 @@ func Sessioner(options ...Options) func(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
if err = sess.Release(); err != nil {
|
||||
if err = s.RawStore.Release(); err != nil {
|
||||
panic("session(release): " + err.Error())
|
||||
}
|
||||
})
|
||||
@@ -273,6 +274,26 @@ func GetSession(req *http.Request) Store {
|
||||
return sess
|
||||
}
|
||||
|
||||
// RegenerateSession
|
||||
func RegenerateSession(resp http.ResponseWriter, req *http.Request) (Store, error) {
|
||||
sess, ok := GetSession(req).(*store)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no session in request context")
|
||||
}
|
||||
|
||||
oldRawStore := sess.RawStore
|
||||
if err := oldRawStore.Release(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
store, err := sess.RegenerateID(resp, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sess.RawStore = store
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// Provider is the interface that provides session manipulations.
|
||||
type Provider interface {
|
||||
// Init initializes session provider.
|
||||
@@ -291,17 +312,34 @@ type Provider interface {
|
||||
GC()
|
||||
}
|
||||
|
||||
var providers = make(map[string]Provider)
|
||||
var providers = make(map[string]func() Provider)
|
||||
|
||||
// Register registers a provider.
|
||||
func Register(name string, provider Provider) {
|
||||
if provider == nil {
|
||||
if reflect.TypeOf(provider).Kind() == reflect.Ptr {
|
||||
// Pointer:
|
||||
RegisterFn(name, func() Provider {
|
||||
return reflect.New(reflect.ValueOf(provider).Elem().Type()).Interface().(Provider)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Not a Pointer
|
||||
RegisterFn(name, func() Provider {
|
||||
return reflect.New(reflect.TypeOf(provider)).Elem().Interface().(Provider)
|
||||
})
|
||||
}
|
||||
|
||||
// RegisterFn registers a provider function.
|
||||
func RegisterFn(name string, providerfn func() Provider) {
|
||||
if providerfn == nil {
|
||||
panic("session: cannot register provider with nil value")
|
||||
}
|
||||
if _, dup := providers[name]; dup {
|
||||
panic(fmt.Errorf("session: cannot register provider '%s' twice", name))
|
||||
}
|
||||
providers[name] = provider
|
||||
|
||||
providers[name] = providerfn
|
||||
}
|
||||
|
||||
// _____
|
||||
@@ -318,12 +356,15 @@ type Manager struct {
|
||||
}
|
||||
|
||||
// NewManager creates and returns a new session manager by given provider name and configuration.
|
||||
// It panics when given provider isn't registered.
|
||||
// It returns an error when requested provider name isn't registered.
|
||||
func NewManager(name string, opt Options) (*Manager, error) {
|
||||
p, ok := providers[name]
|
||||
fn, ok := providers[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("session: unknown provider '%s'(forgotten import?)", name)
|
||||
}
|
||||
|
||||
p := fn()
|
||||
|
||||
return &Manager{p, opt}, p.Init(opt.Maxlifetime, opt.ProviderConfig)
|
||||
}
|
||||
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -18,7 +18,7 @@ gitea.com/go-chi/cache/memcache
|
||||
# gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e
|
||||
## explicit
|
||||
gitea.com/go-chi/captcha
|
||||
# gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee
|
||||
# gitea.com/go-chi/session v0.0.0-20211218221615-e3605d8b28b8
|
||||
## explicit
|
||||
gitea.com/go-chi/session
|
||||
gitea.com/go-chi/session/couchbase
|
||||
|
||||
@@ -135,7 +135,6 @@ textarea:focus,
|
||||
.form {
|
||||
.help {
|
||||
color: #999999;
|
||||
padding-top: .6em;
|
||||
padding-bottom: .6em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user