Compare commits

...

4 Commits

Author SHA1 Message Date
wxiaoguang
aba70084dd
Merge bf2104bce69fd341ded317b4fd69c68c4dcd6ff2 into c2e23d3301b1be2b2ad667184030087f92ad2470 2025-02-19 18:54:15 +01:00
wxiaoguang
c2e23d3301
Fix PR web route permission check (#33636)
Some checks are pending
release-nightly / nightly-binary (push) Waiting to run
release-nightly / nightly-docker-rootful (push) Waiting to run
release-nightly / nightly-docker-rootless (push) Waiting to run
See the FIXME comment in code. Otherwise, if a repo's issue unit is
disabled, then the PRs can't be edited anymore.

By the way, make the permission log output look slightly better.

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: metiftikci <metiftikci@hotmail.com>
2025-02-19 00:55:19 +00:00
metiftikci
84d2159ef6
fix: add missing locale (#33641)
this removed in #23113 but still using in `head_navbar.tmpl`
2025-02-18 16:29:17 -08:00
wxiaoguang
bf2104bce6 fix 2025-01-14 13:19:30 +08:00
6 changed files with 56 additions and 22 deletions

View File

@ -152,7 +152,7 @@ func (p *Permission) ReadableUnitTypes() []unit.Type {
} }
func (p *Permission) LogString() string { func (p *Permission) LogString() string {
format := "<Permission AccessMode=%s, %d Units, %d UnitsMode(s): [ " format := "<Permission AccessMode=%s, %d Units, %d UnitsMode(s): ["
args := []any{p.AccessMode.ToString(), len(p.units), len(p.unitsMode)} args := []any{p.AccessMode.ToString(), len(p.units), len(p.unitsMode)}
for i, u := range p.units { for i, u := range p.units {
@ -164,14 +164,16 @@ func (p *Permission) LogString() string {
config = err.Error() config = err.Error()
} }
} }
format += "\nUnits[%d]: ID: %d RepoID: %d Type: %s Config: %s" format += "\n\tunits[%d]: ID=%d RepoID=%d Type=%s Config=%s"
args = append(args, i, u.ID, u.RepoID, u.Type.LogString(), config) args = append(args, i, u.ID, u.RepoID, u.Type.LogString(), config)
} }
for key, value := range p.unitsMode { for key, value := range p.unitsMode {
format += "\nUnitMode[%-v]: %-v" format += "\n\tunitsMode[%-v]: %-v"
args = append(args, key.LogString(), value.LogString()) args = append(args, key.LogString(), value.LogString())
} }
format += " ]>" format += "\n\teveryoneAccessMode: %-v"
args = append(args, p.everyoneAccessMode)
format += "\n\t]>"
return fmt.Sprintf(format, args...) return fmt.Sprintf(format, args...)
} }

View File

@ -42,12 +42,13 @@ func (err ErrUnitTypeNotExist) Unwrap() error {
// RepoUnit describes all units of a repository // RepoUnit describes all units of a repository
type RepoUnit struct { //revive:disable-line:exported type RepoUnit struct { //revive:disable-line:exported
ID int64 ID int64
RepoID int64 `xorm:"INDEX(s)"` RepoID int64 `xorm:"INDEX(s)"`
Type unit.Type `xorm:"INDEX(s)"` Type unit.Type `xorm:"INDEX(s)"`
Config convert.Conversion `xorm:"TEXT"` Config convert.Conversion `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"` AnonymousAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
} }
func init() { func init() {

View File

@ -5,6 +5,7 @@ package log
import ( import (
"context" "context"
"reflect"
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
@ -175,6 +176,20 @@ func (l *LoggerImpl) IsEnabled() bool {
return l.level.Load() < int32(FATAL) && len(l.eventWriters) > 0 return l.level.Load() < int32(FATAL) && len(l.eventWriters) > 0
} }
func asLogStringer(v any) LogStringer {
if s, ok := v.(LogStringer); ok {
return s
} else if a := reflect.ValueOf(v); a.Kind() == reflect.Struct {
// in case the receiver is a pointer, but the value is a struct
vp := reflect.New(a.Type())
vp.Elem().Set(a)
if s, ok := vp.Interface().(LogStringer); ok {
return s
}
}
return nil
}
// Log prepares the log event, if the level matches, the event will be sent to the writers // Log prepares the log event, if the level matches, the event will be sent to the writers
func (l *LoggerImpl) Log(skip int, level Level, format string, logArgs ...any) { func (l *LoggerImpl) Log(skip int, level Level, format string, logArgs ...any) {
if Level(l.level.Load()) > level { if Level(l.level.Load()) > level {
@ -207,11 +222,11 @@ func (l *LoggerImpl) Log(skip int, level Level, format string, logArgs ...any) {
// handle LogStringer values // handle LogStringer values
for i, v := range msgArgs { for i, v := range msgArgs {
if cv, ok := v.(*ColoredValue); ok { if cv, ok := v.(*ColoredValue); ok {
if s, ok := cv.v.(LogStringer); ok { if ls := asLogStringer(cv.v); ls != nil {
cv.v = logStringFormatter{v: s} cv.v = logStringFormatter{v: ls}
} }
} else if s, ok := v.(LogStringer); ok { } else if ls := asLogStringer(v); ls != nil {
msgArgs[i] = logStringFormatter{v: s} msgArgs[i] = logStringFormatter{v: ls}
} }
} }

View File

@ -116,6 +116,14 @@ func (t testLogString) LogString() string {
return "log-string" return "log-string"
} }
type testLogStringPtrReceiver struct {
Field string
}
func (t *testLogStringPtrReceiver) LogString() string {
return "log-string-ptr-receiver"
}
func TestLoggerLogString(t *testing.T) { func TestLoggerLogString(t *testing.T) {
logger := NewLoggerWithWriters(context.Background(), "test") logger := NewLoggerWithWriters(context.Background(), "test")
@ -124,9 +132,13 @@ func TestLoggerLogString(t *testing.T) {
logger.AddWriters(w1) logger.AddWriters(w1)
logger.Info("%s %s %#v %v", testLogString{}, &testLogString{}, testLogString{Field: "detail"}, NewColoredValue(testLogString{}, FgRed)) logger.Info("%s %s %#v %v", testLogString{}, &testLogString{}, testLogString{Field: "detail"}, NewColoredValue(testLogString{}, FgRed))
logger.Info("%s %s %#v %v", testLogStringPtrReceiver{}, &testLogStringPtrReceiver{}, testLogStringPtrReceiver{Field: "detail"}, NewColoredValue(testLogStringPtrReceiver{}, FgRed))
logger.Close() logger.Close()
assert.Equal(t, []string{"log-string log-string log.testLogString{Field:\"detail\"} \x1b[31mlog-string\x1b[0m\n"}, w1.GetLogs()) assert.Equal(t, []string{
"log-string log-string log.testLogString{Field:\"detail\"} \x1b[31mlog-string\x1b[0m\n",
"log-string-ptr-receiver log-string-ptr-receiver &log.testLogStringPtrReceiver{Field:\"detail\"} \x1b[31mlog-string-ptr-receiver\x1b[0m\n",
}, w1.GetLogs())
} }
func TestLoggerExpressionFilter(t *testing.T) { func TestLoggerExpressionFilter(t *testing.T) {

View File

@ -1702,7 +1702,9 @@ issues.time_estimate_invalid = Time estimate format is invalid
issues.start_tracking_history = started working %s issues.start_tracking_history = started working %s
issues.tracker_auto_close = Timer will be stopped automatically when this issue gets closed issues.tracker_auto_close = Timer will be stopped automatically when this issue gets closed
issues.tracking_already_started = `You have already started time tracking on <a href="%s">another issue</a>!` issues.tracking_already_started = `You have already started time tracking on <a href="%s">another issue</a>!`
issues.stop_tracking = Stop Timer
issues.stop_tracking_history = worked for <b>%[1]s</b> %[2]s issues.stop_tracking_history = worked for <b>%[1]s</b> %[2]s
issues.cancel_tracking = Discard
issues.cancel_tracking_history = `canceled time tracking %s` issues.cancel_tracking_history = `canceled time tracking %s`
issues.del_time = Delete this time log issues.del_time = Delete this time log
issues.add_time_history = added spent time <b>%[1]s</b> %[2]s issues.add_time_history = added spent time <b>%[1]s</b> %[2]s

View File

@ -1196,6 +1196,10 @@ func registerRoutes(m *web.Router) {
}) })
}) })
} }
// FIXME: many "pulls" requests are sent to "issues" endpoints correctly, so the issue endpoints have to tolerate pull request permissions at the moment
m.Group("/{username}/{reponame}/{type:issues}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests))
m.Group("/{username}/{reponame}/{type:pulls}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitPullsReader)
m.Group("/{username}/{reponame}", func() { m.Group("/{username}/{reponame}", func() {
m.Get("/comments/{id}/attachments", repo.GetCommentAttachments) m.Get("/comments/{id}/attachments", repo.GetCommentAttachments)
m.Get("/labels", repo.RetrieveLabelsForList, repo.Labels) m.Get("/labels", repo.RetrieveLabelsForList, repo.Labels)
@ -1203,9 +1207,6 @@ func registerRoutes(m *web.Router) {
m.Get("/milestone/{id}", context.RepoRef(), repo.MilestoneIssuesAndPulls) m.Get("/milestone/{id}", context.RepoRef(), repo.MilestoneIssuesAndPulls)
m.Get("/issues/suggestions", repo.IssueSuggestions) m.Get("/issues/suggestions", repo.IssueSuggestions)
}, optSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader) // issue/pull attachments, labels, milestones }, optSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader) // issue/pull attachments, labels, milestones
m.Group("/{username}/{reponame}/{type:issues}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitIssuesReader)
m.Group("/{username}/{reponame}/{type:pulls}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitPullsReader)
// end "/{username}/{reponame}": view milestone, label, issue, pull, etc // end "/{username}/{reponame}": view milestone, label, issue, pull, etc
m.Group("/{username}/{reponame}/{type:issues}", func() { m.Group("/{username}/{reponame}/{type:issues}", func() {
@ -1224,7 +1225,7 @@ func registerRoutes(m *web.Router) {
m.Get("/search", repo.SearchRepoIssuesJSON) m.Get("/search", repo.SearchRepoIssuesJSON)
}, reqUnitIssuesReader) }, reqUnitIssuesReader)
addIssuesPullsRoutes := func() { addIssuesPullsUpdateRoutes := func() {
// for "/{username}/{reponame}/issues" or "/{username}/{reponame}/pulls" // for "/{username}/{reponame}/issues" or "/{username}/{reponame}/pulls"
m.Group("/{index}", func() { m.Group("/{index}", func() {
m.Post("/title", repo.UpdateIssueTitle) m.Post("/title", repo.UpdateIssueTitle)
@ -1267,8 +1268,9 @@ func registerRoutes(m *web.Router) {
m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin) m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin)
m.Post("/move_pin", reqRepoAdmin, repo.IssuePinMove) m.Post("/move_pin", reqRepoAdmin, repo.IssuePinMove)
} }
m.Group("/{type:issues}", addIssuesPullsRoutes, reqUnitIssuesReader, context.RepoMustNotBeArchived()) // FIXME: many "pulls" requests are sent to "issues" endpoints incorrectly, so the issue endpoints have to tolerate pull request permissions at the moment
m.Group("/{type:pulls}", addIssuesPullsRoutes, reqUnitPullsReader, context.RepoMustNotBeArchived()) m.Group("/{type:issues}", addIssuesPullsUpdateRoutes, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests), context.RepoMustNotBeArchived())
m.Group("/{type:pulls}", addIssuesPullsUpdateRoutes, reqUnitPullsReader, context.RepoMustNotBeArchived())
m.Group("/comments/{id}", func() { m.Group("/comments/{id}", func() {
m.Post("", repo.UpdateCommentContent) m.Post("", repo.UpdateCommentContent)
@ -1292,7 +1294,7 @@ func registerRoutes(m *web.Router) {
m.Post("/delete", repo.DeleteMilestone) m.Post("/delete", repo.DeleteMilestone)
}, reqRepoIssuesOrPullsWriter, context.RepoRef()) }, reqRepoIssuesOrPullsWriter, context.RepoRef())
// FIXME: need to move these routes to the proper place // FIXME: many "pulls" requests are sent to "issues" endpoints incorrectly, need to move these routes to the proper place
m.Group("/issues", func() { m.Group("/issues", func() {
m.Post("/request_review", repo.UpdatePullReviewRequest) m.Post("/request_review", repo.UpdatePullReviewRequest)
m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview) m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview)