Fix various legacy problems (#37092)
1. Fix #36439 2. Fix #37089 3. Fix incorrect layout of admin auth oidc page 4. Fix #35866 5. Fix #35800 6. Fix #36243
This commit is contained in:
10
assets/go-licenses.json
generated
10
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
2
go.mod
2
go.mod
@@ -109,7 +109,6 @@ require (
|
|||||||
github.com/yohcop/openid-go v1.0.1
|
github.com/yohcop/openid-go v1.0.1
|
||||||
github.com/yuin/goldmark v1.8.2
|
github.com/yuin/goldmark v1.8.2
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
github.com/yuin/goldmark-meta v1.1.0
|
|
||||||
gitlab.com/gitlab-org/api/client-go v1.46.0
|
gitlab.com/gitlab-org/api/client-go v1.46.0
|
||||||
go.yaml.in/yaml/v4 v4.0.0-rc.3
|
go.yaml.in/yaml/v4 v4.0.0-rc.3
|
||||||
golang.org/x/crypto v0.49.0
|
golang.org/x/crypto v0.49.0
|
||||||
@@ -283,7 +282,6 @@ require (
|
|||||||
golang.org/x/tools v0.43.0 // indirect
|
golang.org/x/tools v0.43.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401020348-3a24fdc17823 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401020348-3a24fdc17823 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ignore (
|
ignore (
|
||||||
|
|||||||
3
go.sum
3
go.sum
@@ -740,8 +740,6 @@ github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE=
|
|||||||
github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||||
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
|
|
||||||
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
|
|
||||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||||
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||||
@@ -942,7 +940,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package models
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
_ "image/jpeg" // Needed for jpeg support
|
_ "image/jpeg" // Needed for jpeg support
|
||||||
|
|
||||||
@@ -86,11 +87,20 @@ func labelStatsCorrectNumClosedIssuesRepo(ctx context.Context, id int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var milestoneStatsQueryNumIssues = "SELECT `milestone`.id FROM `milestone` WHERE `milestone`.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE `issue`.milestone_id=`milestone`.id AND `issue`.is_closed=?) OR `milestone`.num_issues!=(SELECT COUNT(*) FROM `issue` WHERE `issue`.milestone_id=`milestone`.id)"
|
func milestoneStatsQueryNumIssuesSQL() string {
|
||||||
|
sql := `
|
||||||
|
SELECT "milestone".id FROM "milestone"
|
||||||
|
WHERE (
|
||||||
|
"milestone".num_closed_issues != (SELECT COUNT(*) FROM "issue" WHERE "issue".milestone_id="milestone".id AND "issue".is_closed=?)
|
||||||
|
OR "milestone".num_issues != (SELECT COUNT(*) FROM "issue" WHERE "issue".milestone_id="milestone".id)
|
||||||
|
)
|
||||||
|
`
|
||||||
|
return strings.TrimSpace(strings.ReplaceAll(sql, "\"", "`"))
|
||||||
|
}
|
||||||
|
|
||||||
func milestoneStatsCorrectNumIssuesRepo(ctx context.Context, id int64) error {
|
func milestoneStatsCorrectNumIssuesRepo(ctx context.Context, id int64) error {
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
results, err := e.Query(milestoneStatsQueryNumIssues+" AND `milestone`.repo_id = ?", true, id)
|
results, err := e.Query(milestoneStatsQueryNumIssuesSQL()+" AND `milestone`.repo_id = ?", true, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -192,7 +202,7 @@ func CheckRepoStats(ctx context.Context) error {
|
|||||||
},
|
},
|
||||||
// Milestone.Num{,Closed}Issues
|
// Milestone.Num{,Closed}Issues
|
||||||
{
|
{
|
||||||
statsQuery(milestoneStatsQueryNumIssues, true),
|
statsQuery(milestoneStatsQueryNumIssuesSQL(), true),
|
||||||
issues_model.UpdateMilestoneCounters,
|
issues_model.UpdateMilestoneCounters,
|
||||||
"milestone count 'num_closed_issues' and 'num_issues'",
|
"milestone count 'num_closed_issues' and 'num_issues'",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1323,9 +1323,12 @@ func GetUserByEmail(ctx context.Context, email string) (*User, error) {
|
|||||||
return nil, ErrUserNotExist{Name: email}
|
return nil, ErrUserNotExist{Name: email}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUser checks if a user already exists
|
func GetIndividualUser(ctx context.Context, user *User) (bool, error) {
|
||||||
func GetUser(ctx context.Context, user *User) (bool, error) {
|
has, err := db.GetEngine(ctx).Get(user)
|
||||||
return db.GetEngine(ctx).Get(user)
|
if has && user.Type != UserTypeIndividual {
|
||||||
|
has = false
|
||||||
|
}
|
||||||
|
return has, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByOpenID returns the user object by given OpenID if exists.
|
// GetUserByOpenID returns the user object by given OpenID if exists.
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
|
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
|
||||||
"github.com/yuin/goldmark"
|
"github.com/yuin/goldmark"
|
||||||
highlighting "github.com/yuin/goldmark-highlighting/v2"
|
highlighting "github.com/yuin/goldmark-highlighting/v2"
|
||||||
meta "github.com/yuin/goldmark-meta"
|
|
||||||
"github.com/yuin/goldmark/ast"
|
"github.com/yuin/goldmark/ast"
|
||||||
"github.com/yuin/goldmark/extension"
|
"github.com/yuin/goldmark/extension"
|
||||||
"github.com/yuin/goldmark/parser"
|
"github.com/yuin/goldmark/parser"
|
||||||
@@ -166,7 +165,6 @@ func SpecializedMarkdown(ctx *markup.RenderContext) *GlodmarkRender {
|
|||||||
ParseBlockDollar: setting.Markdown.MathCodeBlockOptions.ParseBlockDollar,
|
ParseBlockDollar: setting.Markdown.MathCodeBlockOptions.ParseBlockDollar,
|
||||||
ParseBlockSquareBrackets: setting.Markdown.MathCodeBlockOptions.ParseBlockSquareBrackets, // this is a bad syntax "\[ ... \]", it conflicts with normal markdown escaping
|
ParseBlockSquareBrackets: setting.Markdown.MathCodeBlockOptions.ParseBlockSquareBrackets, // this is a bad syntax "\[ ... \]", it conflicts with normal markdown escaping
|
||||||
}),
|
}),
|
||||||
meta.Meta,
|
|
||||||
),
|
),
|
||||||
goldmark.WithParserOptions(
|
goldmark.WithParserOptions(
|
||||||
parser.WithAttribute(),
|
parser.WithAttribute(),
|
||||||
|
|||||||
@@ -429,9 +429,12 @@ test
|
|||||||
---
|
---
|
||||||
test
|
test
|
||||||
`,
|
`,
|
||||||
`- item1
|
`<hr/>
|
||||||
- item2
|
<ul>
|
||||||
|
<li>item1</li>
|
||||||
|
<li>item2</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
<p>test</p>
|
<p>test</p>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@@ -443,8 +446,8 @@ anything
|
|||||||
---
|
---
|
||||||
test
|
test
|
||||||
`,
|
`,
|
||||||
`anything
|
`<hr/>
|
||||||
|
<h2>anything</h2>
|
||||||
<p>test</p>
|
<p>test</p>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
@@ -471,14 +474,26 @@ foo: bar
|
|||||||
</details><ul>
|
</details><ul>
|
||||||
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="19"/>task 1</li>
|
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="19"/>task 1</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
// we have our own frontmatter parser, don't need to use github.com/yuin/goldmark-meta
|
||||||
|
{
|
||||||
|
"InvalidFrontmatter",
|
||||||
|
`---
|
||||||
|
foo
|
||||||
|
`,
|
||||||
|
`<hr/>
|
||||||
|
<p>foo</p>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testcases {
|
for _, tt := range testcases {
|
||||||
res, err := markdown.RenderString(markup.NewTestRenderContext(), test.input)
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assert.NoError(t, err, "Unexpected error in testcase: %q", test.name)
|
res, err := markdown.RenderString(markup.NewTestRenderContext(), tt.input)
|
||||||
assert.Equal(t, test.expected, string(res), "Unexpected result in testcase %q", test.name)
|
assert.NoError(t, err, "Unexpected error in testcase: %q", tt.name)
|
||||||
|
assert.Equal(t, tt.expected, string(res), "Unexpected result in testcase %q", tt.name)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ func ExtractMetadata(contents string, out any) (string, error) {
|
|||||||
return string(body), err
|
return string(body), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractMetadata consumes a markdown file, parses YAML frontmatter,
|
// ExtractMetadataBytes consumes a Markdown content, parses YAML frontmatter,
|
||||||
// and returns the frontmatter metadata separated from the markdown content
|
// and returns the frontmatter metadata separated from the Markdown content
|
||||||
func ExtractMetadataBytes(contents []byte, out any) ([]byte, error) {
|
func ExtractMetadataBytes(contents []byte, out any) ([]byte, error) {
|
||||||
var front, body []byte
|
var front, body []byte
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy {
|
|||||||
|
|
||||||
policy.AllowAttrs("src", "autoplay", "controls").OnElements("video")
|
policy.AllowAttrs("src", "autoplay", "controls").OnElements("video")
|
||||||
|
|
||||||
|
// Native support of "<picture><source media=... srcset=...><img src=...></picture>"
|
||||||
|
// ATTENTION: it only works with "auto" theme, because "media" query doesn't work with the theme chosen by end user manually.
|
||||||
|
// For example: browser's color scheme is "dark", but end user chooses "light" theme. Maybe it needs JS to help to make it work.
|
||||||
|
policy.AllowAttrs("media", "srcset").OnElements("source")
|
||||||
|
|
||||||
policy.AllowAttrs("loading").OnElements("img")
|
policy.AllowAttrs("loading").OnElements("img")
|
||||||
|
|
||||||
// Allow generally safe attributes (reference: https://github.com/jch/html-pipeline)
|
// Allow generally safe attributes (reference: https://github.com/jch/html-pipeline)
|
||||||
@@ -86,6 +91,7 @@ func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy {
|
|||||||
"dl", "dt", "dd", "kbd", "q", "samp", "var", "hr", "ruby", "rt", "rp", "li", "tr", "td", "th", "s", "strike", "summary",
|
"dl", "dt", "dd", "kbd", "q", "samp", "var", "hr", "ruby", "rt", "rp", "li", "tr", "td", "th", "s", "strike", "summary",
|
||||||
"details", "caption", "figure", "figcaption",
|
"details", "caption", "figure", "figcaption",
|
||||||
"abbr", "bdo", "cite", "dfn", "mark", "small", "span", "time", "video", "wbr",
|
"abbr", "bdo", "cite", "dfn", "mark", "small", "span", "time", "video", "wbr",
|
||||||
|
"picture", "source",
|
||||||
}
|
}
|
||||||
// FIXME: Need to handle longdesc in img but there is no easy way to do it
|
// FIXME: Need to handle longdesc in img but there is no easy way to do it
|
||||||
policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...)
|
policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...)
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ func TestSanitizer(t *testing.T) {
|
|||||||
`<a href="cbthunderlink://somebase64string)">my custom URL scheme</a>`, `<a href="cbthunderlink://somebase64string)" rel="nofollow">my custom URL scheme</a>`,
|
`<a href="cbthunderlink://somebase64string)">my custom URL scheme</a>`, `<a href="cbthunderlink://somebase64string)" rel="nofollow">my custom URL scheme</a>`,
|
||||||
`<a href="matrix:roomid/psumPMeAfzgAeQpXMG:feneas.org?action=join">my custom URL scheme</a>`, `<a href="matrix:roomid/psumPMeAfzgAeQpXMG:feneas.org?action=join" rel="nofollow">my custom URL scheme</a>`,
|
`<a href="matrix:roomid/psumPMeAfzgAeQpXMG:feneas.org?action=join">my custom URL scheme</a>`, `<a href="matrix:roomid/psumPMeAfzgAeQpXMG:feneas.org?action=join" rel="nofollow">my custom URL scheme</a>`,
|
||||||
|
|
||||||
|
// picture
|
||||||
|
`<picture><source media="a"><source media="b"><img alt="c" src="d"></picture>`, `<picture><source media="a"><source media="b"><img alt="c" src="d"></picture>`,
|
||||||
|
|
||||||
// Disallow dangerous url schemes
|
// Disallow dangerous url schemes
|
||||||
`<a href="javascript:alert('xss')">bad</a>`, `bad`,
|
`<a href="javascript:alert('xss')">bad</a>`, `bad`,
|
||||||
`<a href="vbscript:no">bad</a>`, `bad`,
|
`<a href="vbscript:no">bad</a>`, `bad`,
|
||||||
|
|||||||
@@ -633,16 +633,15 @@ func createUserInContext(ctx *context.Context, tpl templates.TplName, form any,
|
|||||||
case setting.OAuth2AccountLinkingAuto:
|
case setting.OAuth2AccountLinkingAuto:
|
||||||
var user *user_model.User
|
var user *user_model.User
|
||||||
user = &user_model.User{Name: u.Name}
|
user = &user_model.User{Name: u.Name}
|
||||||
hasUser, err := user_model.GetUser(ctx, user)
|
hasUser, err := user_model.GetIndividualUser(ctx, user)
|
||||||
if !hasUser || err != nil {
|
if !hasUser || err != nil {
|
||||||
user = &user_model.User{Email: u.Email}
|
user = &user_model.User{Email: u.Email}
|
||||||
hasUser, err = user_model.GetUser(ctx, user)
|
hasUser, err = user_model.GetIndividualUser(ctx, user)
|
||||||
if !hasUser || err != nil {
|
if !hasUser || err != nil {
|
||||||
ctx.ServerError("UserLinkAccount", err)
|
ctx.ServerError("UserLinkAccount", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: probably we should respect 'remember' user's choice...
|
// TODO: probably we should respect 'remember' user's choice...
|
||||||
oauth2LinkAccount(ctx, user, possibleLinkAccountData, true)
|
oauth2LinkAccount(ctx, user, possibleLinkAccountData, true)
|
||||||
return false // user is already created here, all redirects are handled
|
return false // user is already created here, all redirects are handled
|
||||||
|
|||||||
@@ -482,7 +482,7 @@ func oAuth2UserLoginCallback(ctx *context.Context, authSource *auth.Source, requ
|
|||||||
LoginSource: authSource.ID,
|
LoginSource: authSource.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
hasUser, err := user_model.GetUser(ctx, user)
|
hasUser, err := user_model.GetIndividualUser(ctx, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, goth.User{}, err
|
return nil, goth.User{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -451,6 +451,7 @@ func NewReleasePost(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.Target = util.IfZero(form.Target, ctx.Repo.Repository.DefaultBranch)
|
||||||
if exist, _ := git_model.IsBranchExist(ctx, ctx.Repo.Repository.ID, form.Target); !exist {
|
if exist, _ := git_model.IsBranchExist(ctx, ctx.Repo.Repository.ID, form.Target); !exist {
|
||||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.target_branch_not_exist"), tplReleaseNew, &form)
|
ctx.RenderWithErrDeprecated(ctx.Tr("form.target_branch_not_exist"), tplReleaseNew, &form)
|
||||||
return
|
return
|
||||||
@@ -564,6 +565,11 @@ func EditRelease(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if rel.IsTag {
|
||||||
|
ctx.NotFound(err) // for a pure tag release, don't allow to edit it as a release
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["ID"] = rel.ID
|
ctx.Data["ID"] = rel.ID
|
||||||
ctx.Data["tag_name"] = rel.TagName
|
ctx.Data["tag_name"] = rel.TagName
|
||||||
ctx.Data["tag_target"] = util.IfZero(rel.Target, ctx.Repo.Repository.DefaultBranch)
|
ctx.Data["tag_target"] = util.IfZero(rel.Target, ctx.Repo.Repository.DefaultBranch)
|
||||||
@@ -613,7 +619,7 @@ func EditReleasePost(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if rel.IsTag {
|
if rel.IsTag {
|
||||||
ctx.NotFound(err)
|
ctx.NotFound(err) // for a pure tag release, don't allow to edit it as a release
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["tag_name"] = rel.TagName
|
ctx.Data["tag_name"] = rel.TagName
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func UserSignIn(ctx context.Context, username, password string) (*user_model.Use
|
|||||||
}
|
}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
hasUser, err := user_model.GetUser(ctx, user)
|
hasUser, err := user_model.GetIndividualUser(ctx, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (source *Source) refresh(ctx context.Context, provider goth.Provider, u *us
|
|||||||
LoginSource: u.LoginSourceID,
|
LoginSource: u.LoginSourceID,
|
||||||
}
|
}
|
||||||
|
|
||||||
hasUser, err := user_model.GetUser(ctx, user)
|
hasUser, err := user_model.GetIndividualUser(ctx, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,37 +84,66 @@
|
|||||||
<h5>GMail Settings:</h5>
|
<h5>GMail Settings:</h5>
|
||||||
<p>Host: smtp.gmail.com, Port: 587, Enable TLS Encryption: true</p>
|
<p>Host: smtp.gmail.com, Port: 587, Enable TLS Encryption: true</p>
|
||||||
|
|
||||||
<h5 class="oauth2">{{ctx.Locale.Tr "admin.auths.tips.oauth2.general"}}:</h5>
|
<div class="oauth2">
|
||||||
<p class="oauth2">{{ctx.Locale.Tr "admin.auths.tips.oauth2.general.tip"}} <b id="oauth2-callback-url"></b></p>
|
<h5>{{ctx.Locale.Tr "admin.auths.tips.oauth2.general"}}</h5>
|
||||||
|
<p>{{ctx.Locale.Tr "admin.auths.tips.oauth2.general.tip"}} <b id="oauth2-callback-url"></b></p>
|
||||||
<h5 class="ui top attached header">{{ctx.Locale.Tr "admin.auths.tip.oauth2_provider"}}</h5>
|
</div>
|
||||||
<div class="ui attached segment">
|
<div class="oauth2 tw-mt-4">
|
||||||
<li>Bitbucket</li>
|
<h5>{{ctx.Locale.Tr "admin.auths.tip.oauth2_provider"}}</h5>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.bitbucket" "https://bitbucket.org/account/user/{your-username}/oauth-consumers/new"}}</span>
|
<ul>
|
||||||
<li>Dropbox</li>
|
<li>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.dropbox" "https://www.dropbox.com/developers/apps"}}</span>
|
Bitbucket
|
||||||
<li>Facebook</li>
|
<div>{{ctx.Locale.Tr "admin.auths.tip.bitbucket" "https://bitbucket.org/account/user/{your-username}/oauth-consumers/new"}}</div>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.facebook" "https://developers.facebook.com/apps"}}</span>
|
</li>
|
||||||
<li>GitHub</li>
|
<li>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.github" "https://github.com/settings/applications/new"}}</span>
|
Dropbox
|
||||||
<li>GitLab</li>
|
<div>{{ctx.Locale.Tr "admin.auths.tip.dropbox" "https://www.dropbox.com/developers/apps"}}</div>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.gitlab_new" "https://gitlab.com/-/profile/applications"}}</span>
|
</li>
|
||||||
<li>Google</li>
|
<li>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.google_plus" "https://console.developers.google.com/"}}</span>
|
Facebook
|
||||||
<li>OpenID Connect</li>
|
<div>{{ctx.Locale.Tr "admin.auths.tip.facebook" "https://developers.facebook.com/apps"}}</div>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.openid_connect"}}</span>
|
</li>
|
||||||
<li>Twitter</li>
|
<li>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.twitter" "https://dev.twitter.com/apps"}}</span>
|
GitHub
|
||||||
<li>Discord</li>
|
<div>{{ctx.Locale.Tr "admin.auths.tip.github" "https://github.com/settings/applications/new"}}</div>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.discord" "https://discordapp.com/developers/applications/me"}}</span>
|
</li>
|
||||||
<li>Gitea</li>
|
<li>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.gitea" "https://docs.gitea.com/development/oauth2-provider"}}</span>
|
GitLab
|
||||||
<li>Nextcloud</li>
|
<div>{{ctx.Locale.Tr "admin.auths.tip.gitlab_new" "https://gitlab.com/-/profile/applications"}}</div>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.nextcloud"}}</span>
|
</li>
|
||||||
<li>Yandex</li>
|
<li>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.yandex" "https://oauth.yandex.com/client/new"}}</span>
|
Google
|
||||||
<li>Mastodon</li>
|
<div>{{ctx.Locale.Tr "admin.auths.tip.google_plus" "https://console.developers.google.com/"}}</div>
|
||||||
<span>{{ctx.Locale.Tr "admin.auths.tip.mastodon"}}</span>
|
</li>
|
||||||
|
<li>
|
||||||
|
OpenID Connect
|
||||||
|
<div>{{ctx.Locale.Tr "admin.auths.tip.openid_connect"}}</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Twitter
|
||||||
|
<div>{{ctx.Locale.Tr "admin.auths.tip.twitter" "https://dev.twitter.com/apps"}}</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Discord
|
||||||
|
<div>{{ctx.Locale.Tr "admin.auths.tip.discord" "https://discordapp.com/developers/applications/me"}}</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Gitea
|
||||||
|
<div>{{ctx.Locale.Tr "admin.auths.tip.gitea" "https://docs.gitea.com/development/oauth2-provider"}}</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Nextcloud
|
||||||
|
<div>{{ctx.Locale.Tr "admin.auths.tip.nextcloud"}}</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Yandex
|
||||||
|
<div>{{ctx.Locale.Tr "admin.auths.tip.yandex" "https://oauth.yandex.com/client/new"}}</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Mastodon
|
||||||
|
<div>{{ctx.Locale.Tr "admin.auths.tip.mastodon"}}</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -290,7 +290,9 @@ In markup content, we always use bottom margin for all elements */
|
|||||||
We decide which to show via `data-gitea-theme-dark` on `<html>`, which is
|
We decide which to show via `data-gitea-theme-dark` on `<html>`, which is
|
||||||
mirrored from `--is-dark-theme` in JS (so it also works with auto/custom themes).
|
mirrored from `--is-dark-theme` in JS (so it also works with auto/custom themes).
|
||||||
*/
|
*/
|
||||||
|
html[data-gitea-theme-dark="true"] .markup a[href*="#gh-light-mode-only"],
|
||||||
html[data-gitea-theme-dark="true"] .markup img[src*="#gh-light-mode-only"],
|
html[data-gitea-theme-dark="true"] .markup img[src*="#gh-light-mode-only"],
|
||||||
|
html[data-gitea-theme-dark="false"] .markup a[href*="#gh-dark-mode-only"],
|
||||||
html[data-gitea-theme-dark="false"] .markup img[src*="#gh-dark-mode-only"] {
|
html[data-gitea-theme-dark="false"] .markup img[src*="#gh-dark-mode-only"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {POST} from '../modules/fetch.ts';
|
import {POST} from '../modules/fetch.ts';
|
||||||
import {hideToastsAll, showErrorToast} from '../modules/toast.ts';
|
import {hideToastsAll, showErrorToast} from '../modules/toast.ts';
|
||||||
import {getComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
import {getComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts';
|
||||||
import {hideElem, showElem} from '../utils/dom.ts';
|
import {hideElem} from '../utils/dom.ts';
|
||||||
import {fomanticQuery} from '../modules/fomantic/base.ts';
|
import {fomanticQuery} from '../modules/fomantic/base.ts';
|
||||||
import {registerGlobalEventFunc, registerGlobalInitFunc} from '../modules/observer.ts';
|
import {registerGlobalEventFunc, registerGlobalInitFunc} from '../modules/observer.ts';
|
||||||
import {htmlEscape} from '../utils/html.ts';
|
import {htmlEscape} from '../utils/html.ts';
|
||||||
@@ -36,12 +36,12 @@ function initTagNameEditor(elForm: HTMLFormElement) {
|
|||||||
const hideTargetInput = function(tagNameInput: HTMLInputElement) {
|
const hideTargetInput = function(tagNameInput: HTMLInputElement) {
|
||||||
const value = tagNameInput.value;
|
const value = tagNameInput.value;
|
||||||
const tagHelper = elForm.querySelector('.tag-name-helper')!;
|
const tagHelper = elForm.querySelector('.tag-name-helper')!;
|
||||||
|
// Old behavior: if the tag already exists, hide the target branch selector and show a helper text to indicate the tag already exists.
|
||||||
|
// However, it is not right: when creating from an existing tag (not a draft or release yet), it still needs the "target branch"
|
||||||
|
// So the new logic here: don't hide the target branch selector.
|
||||||
if (existingTags.includes(value)) {
|
if (existingTags.includes(value)) {
|
||||||
// If the tag already exists, hide the target branch selector.
|
|
||||||
hideElem(elForm.querySelectorAll('.tag-target-selector'));
|
|
||||||
tagHelper.textContent = existingTagHelperText;
|
tagHelper.textContent = existingTagHelperText;
|
||||||
} else {
|
} else {
|
||||||
showElem(elForm.querySelectorAll('.tag-target-selector'));
|
|
||||||
tagHelper.textContent = value ? newTagHelperText : defaultTagHelperText;
|
tagHelper.textContent = value ? newTagHelperText : defaultTagHelperText;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user