Compare commits
10 commits
5a4b19435d
...
26e09364b9
Author | SHA1 | Date | |
---|---|---|---|
26e09364b9 | |||
![]() |
a1986507b7 | ||
![]() |
fb8de41e05 | ||
![]() |
a81c6561e3 | ||
![]() |
5afb0294f4 | ||
![]() |
7ee4804b9c | ||
![]() |
4c3dcdf815 | ||
![]() |
dfa114bfcb | ||
![]() |
268569b462 | ||
![]() |
751028549d |
14 changed files with 227 additions and 22 deletions
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -4,6 +4,34 @@ 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.20.2](https://github.com/go-gitea/gitea/releases/tag/1.20.2) - 2023-07-29
|
||||
|
||||
* ENHANCEMENTS
|
||||
* Calculate MAX_WORKERS default value by CPU number (#26177) (#26183)
|
||||
* Display deprecated warning in admin panel pages as well as in the log file (#26094) (#26154)
|
||||
* BUGFIXES
|
||||
* Fix allowed user types setting problem (#26200) (#26206)
|
||||
* Fix handling of plenty Nuget package versions (#26075) (#26173)
|
||||
* Fix UI regression of asciinema player (#26159) (#26162)
|
||||
* Fix LFS object list style (#26133) (#26147)
|
||||
* Fix allowed user types setting problem (#26200) (#26206)
|
||||
* Prevent primary key update on migration (#26192) (#26199)
|
||||
* Fix bug when pushing to a pull request which enabled dismiss approval automatically (#25882) (#26158)
|
||||
* Fix bugs in LFS meta garbage collection (#26122) (#26157)
|
||||
* Update xorm version (#26128) (#26150)
|
||||
* Remove "misc" scope check from public API endpoints (#26134) (#26149)
|
||||
* Fix CLI allowing creation of access tokens with existing name (#26071) (#26144)
|
||||
* Fix incorrect router logger (#26137) (#26143)
|
||||
* Improve commit graph alignment and truncating (#26112) (#26127)
|
||||
* Avoid writing config file if not installed (#26107) (#26113)
|
||||
* Fix escape problems in the branch selector (#25875) (#26103)
|
||||
* Fix handling of Debian files with trailing slash (#26087) (#26098)
|
||||
* Fix Missing 404 swagger response docs for /admin/users/{username} (#26086) (#26089)
|
||||
* Use stderr as fallback if the log file can't be opened (#26074) (#26083)
|
||||
* Increase table cell horizontal padding (#26140) (#26142)
|
||||
* Fix wrong workflow status when rerun a job in an already finished workflow (#26119) (#26124)
|
||||
* Fix duplicated url prefix on issue context menu (#26066) (#26067)
|
||||
|
||||
## [1.20.1](https://github.com/go-gitea/gitea/releases/tag/1.20.1) - 2023-07-22
|
||||
|
||||
* SECURITY
|
||||
|
|
|
@ -65,10 +65,10 @@ RUN addgroup \
|
|||
-s /bin/bash \
|
||||
-u 1000 \
|
||||
-G git \
|
||||
git && \
|
||||
echo "git:*" | chpasswd -e
|
||||
_gitea && \
|
||||
echo "_gitea:*" | chpasswd -e
|
||||
|
||||
ENV USER git
|
||||
ENV USER _gitea
|
||||
ENV GITEA_CUSTOM /data/gitea
|
||||
|
||||
VOLUME ["/data"]
|
||||
|
|
2
Makefile
2
Makefile
|
@ -89,7 +89,7 @@ endif
|
|||
VERSION = ${GITEA_VERSION}
|
||||
|
||||
# SemVer
|
||||
FORGEJO_VERSION := 5.0.0+0-gitea-1.20.1
|
||||
FORGEJO_VERSION := 5.0.1+0-gitea-1.20.2
|
||||
|
||||
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)" -X "code.gitea.io/gitea/routers/api/forgejo/v1.ForgejoVersion=$(FORGEJO_VERSION)"
|
||||
|
||||
|
|
|
@ -280,3 +280,9 @@
|
|||
team_id: 20
|
||||
type: 9 # package
|
||||
access_mode: 2
|
||||
|
||||
-
|
||||
id: 48
|
||||
team_id: 2
|
||||
type: 8
|
||||
access_mode: 2
|
||||
|
|
|
@ -20,7 +20,7 @@ func ChangeContainerMetadataMultiArch(x *xorm.Engine) error {
|
|||
}
|
||||
|
||||
type PackageVersion struct {
|
||||
ID int64 `xorm:"pk"`
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
MetadataJSON string `xorm:"metadata_json"`
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
|
|||
LFS.JWTSecretBytes = make([]byte, 32)
|
||||
n, err := base64.RawURLEncoding.Decode(LFS.JWTSecretBytes, []byte(LFS.JWTSecretBase64))
|
||||
|
||||
if (err != nil || n != 32) && InstallLock {
|
||||
if err != nil || n != 32 {
|
||||
LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating JWT Secret for custom config: %v", err)
|
||||
|
|
|
@ -188,15 +188,33 @@ func loadServiceFrom(rootCfg ConfigProvider) {
|
|||
Service.EnableUserHeatmap = sec.Key("ENABLE_USER_HEATMAP").MustBool(true)
|
||||
Service.AutoWatchNewRepos = sec.Key("AUTO_WATCH_NEW_REPOS").MustBool(true)
|
||||
Service.AutoWatchOnChanges = sec.Key("AUTO_WATCH_ON_CHANGES").MustBool(false)
|
||||
Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
||||
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
|
||||
Service.AllowedUserVisibilityModes = sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",")
|
||||
if len(Service.AllowedUserVisibilityModes) != 0 {
|
||||
modes := sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",")
|
||||
if len(modes) != 0 {
|
||||
Service.AllowedUserVisibilityModes = []string{}
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{false, false, false}
|
||||
for _, sMode := range Service.AllowedUserVisibilityModes {
|
||||
Service.AllowedUserVisibilityModesSlice[structs.VisibilityModes[sMode]] = true
|
||||
for _, sMode := range modes {
|
||||
if tp, ok := structs.VisibilityModes[sMode]; ok { // remove unsupported modes
|
||||
Service.AllowedUserVisibilityModes = append(Service.AllowedUserVisibilityModes, sMode)
|
||||
Service.AllowedUserVisibilityModesSlice[tp] = true
|
||||
} else {
|
||||
log.Warn("ALLOWED_USER_VISIBILITY_MODES %s is unsupported", sMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(Service.AllowedUserVisibilityModes) == 0 {
|
||||
Service.AllowedUserVisibilityModes = []string{"public", "limited", "private"}
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
|
||||
}
|
||||
|
||||
Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").String()
|
||||
if Service.DefaultUserVisibility == "" {
|
||||
Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
|
||||
} else if !Service.AllowedUserVisibilityModesSlice[structs.VisibilityModes[Service.DefaultUserVisibility]] {
|
||||
log.Warn("DEFAULT_USER_VISIBILITY %s is wrong or not in ALLOWED_USER_VISIBILITY_MODES, using first allowed", Service.DefaultUserVisibility)
|
||||
Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
|
||||
}
|
||||
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
|
||||
Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
|
||||
Service.DefaultOrgVisibilityMode = structs.VisibilityModes[Service.DefaultOrgVisibility]
|
||||
Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool()
|
||||
|
|
|
@ -6,6 +6,8 @@ package setting
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -44,3 +46,87 @@ EMAIL_DOMAIN_BLOCKLIST = d3, *.b
|
|||
assert.True(t, match(Service.EmailDomainBlockList, "foo.b"))
|
||||
assert.False(t, match(Service.EmailDomainBlockList, "d1"))
|
||||
}
|
||||
|
||||
func TestLoadServiceVisibilityModes(t *testing.T) {
|
||||
oldService := Service
|
||||
defer func() {
|
||||
Service = oldService
|
||||
}()
|
||||
|
||||
kases := map[string]func(){
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = limited
|
||||
`: func() {
|
||||
assert.Equal(t, "limited", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
},
|
||||
`
|
||||
[service]
|
||||
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "limited", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = my_type
|
||||
ALLOWED_USER_VISIBILITY_MODES = limited,private
|
||||
`: func() {
|
||||
assert.Equal(t, "limited", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"limited", "private"}, Service.AllowedUserVisibilityModes)
|
||||
},
|
||||
`
|
||||
[service]
|
||||
DEFAULT_USER_VISIBILITY = public
|
||||
ALLOWED_USER_VISIBILITY_MODES = public, limit, privated
|
||||
`: func() {
|
||||
assert.Equal(t, "public", Service.DefaultUserVisibility)
|
||||
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
|
||||
assert.Equal(t, []string{"public"}, Service.AllowedUserVisibilityModes)
|
||||
},
|
||||
}
|
||||
|
||||
for kase, fun := range kases {
|
||||
t.Run(kase, func(t *testing.T) {
|
||||
cfg, err := NewConfigProviderFromData(kase)
|
||||
assert.NoError(t, err)
|
||||
loadServiceFrom(cfg)
|
||||
fun()
|
||||
// reset
|
||||
Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
|
||||
Service.AllowedUserVisibilityModes = []string{}
|
||||
Service.DefaultUserVisibility = ""
|
||||
Service.DefaultUserVisibilityMode = structs.VisibleTypePublic
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,9 +263,10 @@ func registerRoutes(m *web.Route) {
|
|||
}
|
||||
}
|
||||
|
||||
reqUnitAccess := func(unitType unit.Type, accessMode perm.AccessMode) func(ctx *context.Context) {
|
||||
reqUnitAccess := func(unitType unit.Type, accessMode perm.AccessMode, ignoreGlobal bool) func(ctx *context.Context) {
|
||||
return func(ctx *context.Context) {
|
||||
if unitType.UnitGlobalDisabled() {
|
||||
// only check global disabled units when ignoreGlobal is false
|
||||
if !ignoreGlobal && unitType.UnitGlobalDisabled() {
|
||||
ctx.NotFound(unitType.String(), nil)
|
||||
return
|
||||
}
|
||||
|
@ -842,7 +843,7 @@ func registerRoutes(m *web.Route) {
|
|||
m.Group("", func() {
|
||||
m.Get("", org.Projects)
|
||||
m.Get("/{id}", org.ViewProject)
|
||||
}, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead))
|
||||
}, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true))
|
||||
m.Group("", func() { //nolint:dupl
|
||||
m.Get("/new", org.RenderNewProject)
|
||||
m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
|
||||
|
@ -863,17 +864,17 @@ func registerRoutes(m *web.Route) {
|
|||
m.Post("/move", org.MoveIssues)
|
||||
})
|
||||
})
|
||||
}, reqSignIn, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite), func(ctx *context.Context) {
|
||||
}, reqSignIn, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true), func(ctx *context.Context) {
|
||||
if ctx.ContextUser.IsIndividual() && ctx.ContextUser.ID != ctx.Doer.ID {
|
||||
ctx.NotFound("NewProject", nil)
|
||||
return
|
||||
}
|
||||
})
|
||||
}, repo.MustEnableProjects)
|
||||
})
|
||||
|
||||
m.Group("", func() {
|
||||
m.Get("/code", user.CodeSearch)
|
||||
}, reqUnitAccess(unit.TypeCode, perm.AccessModeRead))
|
||||
}, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false))
|
||||
}, ignSignIn, context_service.UserAssignmentWeb(), context.OrgAssignment()) // for "/{username}/-" (packages, projects, code)
|
||||
|
||||
// ***** Release Attachment Download without Signin
|
||||
|
|
|
@ -5,6 +5,7 @@ package webhook
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -111,7 +112,11 @@ func handler(items ...int64) []int64 {
|
|||
for _, taskID := range items {
|
||||
task, err := webhook_model.GetHookTaskByID(ctx, taskID)
|
||||
if err != nil {
|
||||
log.Error("GetHookTaskByID[%d] failed: %v", taskID, err)
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
log.Warn("GetHookTaskByID[%d] warn: %v", taskID, err)
|
||||
} else {
|
||||
log.Error("GetHookTaskByID[%d] failed: %v", taskID, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{{.locale.Tr "repo.commits.no_commits" $.BaseBranch $.HeadBranch}} {{if .RefName}}({{.RefName}}){{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="commits-table-right">
|
||||
<div class="commits-table-right gt-whitespace-nowrap">
|
||||
{{if .PageIsCommits}}
|
||||
<form class="ignore-dirty" action="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/search">
|
||||
<div class="ui tiny search input">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="four wide column">
|
||||
<div class="ui fluid vertical menu">
|
||||
<div class="header item">{{.locale.Tr "org.settings"}}</div>
|
||||
<div class="header item">{{.locale.Tr "repo.settings"}}</div>
|
||||
<a class="{{if .PageIsSettingsOptions}}active {{end}}item" href="{{.RepoLink}}/settings">
|
||||
{{.locale.Tr "repo.settings.options"}}
|
||||
</a>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="four wide column">
|
||||
<div class="ui fluid vertical menu">
|
||||
<div class="header item">{{.locale.Tr "org.settings"}}</div>
|
||||
<div class="header item">{{.locale.Tr "settings"}}</div>
|
||||
<a class="{{if .PageIsSettingsProfile}}active {{end}}item" href="{{AppSubUrl}}/user/settings">
|
||||
{{.locale.Tr "settings.profile"}}
|
||||
</a>
|
||||
|
|
61
tests/integration/org_project_test.go
Normal file
61
tests/integration/org_project_test.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/tests"
|
||||
)
|
||||
|
||||
func TestOrgProjectAccess(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
// disable repo project unit
|
||||
unit_model.DisabledRepoUnits = []unit_model.Type{unit_model.TypeProjects}
|
||||
|
||||
// repo project, 404
|
||||
req := NewRequest(t, "GET", "/user2/repo1/projects")
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
// user project, 200
|
||||
req = NewRequest(t, "GET", "/user2/-/projects")
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// org project, 200
|
||||
req = NewRequest(t, "GET", "/user3/-/projects")
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// change the org's visibility to private
|
||||
session := loginUser(t, "user2")
|
||||
req = NewRequestWithValues(t, "POST", "/org/user3/settings", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, "/user3/-/projects"),
|
||||
"name": "user3",
|
||||
"visibility": "2",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// user4 can still access the org's project because its team(team1) has the permission
|
||||
session = loginUser(t, "user4")
|
||||
req = NewRequest(t, "GET", "/user3/-/projects")
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// disable team1's project unit
|
||||
session = loginUser(t, "user2")
|
||||
req = NewRequestWithValues(t, "POST", "/org/user3/teams/team1/edit", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, "/user3/-/projects"),
|
||||
"team_name": "team1",
|
||||
"repo_access": "specific",
|
||||
"permission": "read",
|
||||
"unit_8": "0",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// user4 can no longer access the org's project
|
||||
session = loginUser(t, "user4")
|
||||
req = NewRequest(t, "GET", "/user3/-/projects")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
Loading…
Reference in a new issue