Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
* upstream/main:
  Add more package registry paths to the labeler (go-gitea#27032)
  Extract auth middleware from service (go-gitea#27028)
  S3: log human readable error on connection failure (go-gitea#26856)
  [skip ci] Updated translations via Crowdin
  Fix "delete" modal dialog for issue/PR (go-gitea#27015)
  Fix context cache bug & enable context cache for dashabord commits' authors (go-gitea#26991)
  fix: typo (go-gitea#27009)
  Use secure cookie for HTTPS sites (go-gitea#26999)
  Add fetch wrappers, ignore network errors in actions view (go-gitea#26985)
  • Loading branch information
zjjhot committed Sep 12, 2023
2 parents 793a96b + e481638 commit 85b3127
Show file tree
Hide file tree
Showing 28 changed files with 493 additions and 391 deletions.
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ kind/build:

theme/package-registry:
- "modules/packages/**"
- "services/packages/**"
- "routers/api/packages/**"
- "routers/web/shared/packages/**"

kind/cli:
- "cmd/**"
Expand Down
2 changes: 1 addition & 1 deletion cmd/migrate_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func runMigrateStorage(ctx *cli.Context) error {
case string(setting.LocalStorageType):
p := ctx.String("path")
if p == "" {
log.Fatal("Path must be given when storage is loal")
log.Fatal("Path must be given when storage is local")
return nil
}
dstStorage, err = storage.NewLocalStorage(
Expand Down
4 changes: 2 additions & 2 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1746,8 +1746,8 @@ LEVEL = Info
;; Session cookie name
;COOKIE_NAME = i_like_gitea
;;
;; If you use session in https only, default is false
;COOKIE_SECURE = false
;; If you use session in https only: true or false. If not set, it defaults to `true` if the ROOT_URL is an HTTPS URL.
;COOKIE_SECURE =
;;
;; Session GC time interval in seconds, default is 86400 (1 day)
;GC_INTERVAL_TIME = 86400
Expand Down
2 changes: 1 addition & 1 deletion docs/content/administration/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ and

- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, redis-cluster, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string. Relative paths will be made absolute against _`AppWorkPath`_.
- `COOKIE_SECURE`: **false**: Enable this to force using HTTPS for all session access.
- `COOKIE_SECURE`:**_empty_**: `true` or `false`. Enable this to force using HTTPS for all session access. If not set, it defaults to `true` if the ROOT_URL is an HTTPS URL.
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
- `GC_INTERVAL_TIME`: **86400**: GC interval in seconds.
- `SESSION_LIFE_TIME`: **86400**: Session life time in seconds, default is 86400 (1 day)
Expand Down
2 changes: 1 addition & 1 deletion docs/content/administration/config-cheat-sheet.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ Gitea 创建以下非唯一队列:

- `PROVIDER`: **memory**:会话存储引擎 \[memory, file, redis, redis-cluster, db, mysql, couchbase, memcache, postgres\]。设置为 `db` 将会重用 `[database]` 的配置信息。
- `PROVIDER_CONFIG`: **data/sessions**:对于文件,为根路径;对于 db,为空(将使用数据库配置);对于其他引擎,为连接字符串。相对路径将根据 _`AppWorkPath`_ 绝对化。
- `COOKIE_SECURE`: **false**:启用此选项以强制在所有会话访问中使用 HTTPS。
- `COOKIE_SECURE`: **_empty_**`true``false`启用此选项以强制在所有会话访问中使用 HTTPS。如果没有设置,当 ROOT_URL 是 https 链接的时候默认设置为 true
- `COOKIE_NAME`: **i\_like\_gitea**:用于会话 ID 的 cookie 名称。
- `GC_INTERVAL_TIME`: **86400**:GC 间隔时间,以秒为单位。
- `SESSION_LIFE_TIME`: **86400**:会话生命周期,以秒为单位,默认为 86400(1 天)。
Expand Down
6 changes: 6 additions & 0 deletions docs/content/contributing/guidelines-frontend.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ it's recommended to use `const _promise = asyncFoo()` to tell readers
that this is done by purpose, we want to call the async function and ignore the Promise.
Some lint rules and IDEs also have warnings if the returned Promise is not handled.

### Fetching data

To fetch data, use the wrapper functions `GET`, `POST` etc. from `modules/fetch.js`. They
accept a `data` option for the content, will automatically set CSFR token and return a
Promise for a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response).

### HTML Attributes and `dataset`

The usage of `dataset` is forbidden, its camel-casing behaviour makes it hard to grep for attributes.
Expand Down
8 changes: 6 additions & 2 deletions models/avatars/avatar.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
return DefaultAvatarLink()
}

enableFederatedAvatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureEnableFederatedAvatar)
disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar,
setting.GetDefaultDisableGravatar(),
)

enableFederatedAvatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureEnableFederatedAvatar,
setting.GetDefaultEnableFederatedAvatar(disableGravatar))

var err error
if enableFederatedAvatar && system_model.LibravatarService != nil {
Expand All @@ -174,7 +179,6 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
return urlStr
}

disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar)
if !disableGravatar {
// copy GravatarSourceURL, because we will modify its Path.
avatarURLCopy := *system_model.GravatarSourceURL
Expand Down
4 changes: 2 additions & 2 deletions models/fixtures/system_setting.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
-
id: 1
setting_key: 'disable_gravatar'
setting_key: 'picture.disable_gravatar'
setting_value: 'false'
version: 1
created: 1653533198
updated: 1653533198

-
id: 2
setting_key: 'enable_federated_avatar'
setting_key: 'picture.enable_federated_avatar'
setting_value: 'false'
version: 1
created: 1653533198
Expand Down
62 changes: 29 additions & 33 deletions models/system/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,14 @@ func GetSetting(ctx context.Context, key string) (*Setting, error) {
const contextCacheKey = "system_setting"

// GetSettingWithCache returns the setting value via the key
func GetSettingWithCache(ctx context.Context, key string) (string, error) {
func GetSettingWithCache(ctx context.Context, key, defaultVal string) (string, error) {
return cache.GetWithContextCache(ctx, contextCacheKey, key, func() (string, error) {
return cache.GetString(genSettingCacheKey(key), func() (string, error) {
res, err := GetSetting(ctx, key)
if err != nil {
if IsErrSettingIsNotExist(err) {
return defaultVal, nil
}
return "", err
}
return res.SettingValue, nil
Expand All @@ -108,17 +111,21 @@ func GetSettingWithCache(ctx context.Context, key string) (string, error) {

// GetSettingBool return bool value of setting,
// none existing keys and errors are ignored and result in false
func GetSettingBool(ctx context.Context, key string) bool {
s, _ := GetSetting(ctx, key)
if s == nil {
return false
func GetSettingBool(ctx context.Context, key string, defaultVal bool) (bool, error) {
s, err := GetSetting(ctx, key)
switch {
case err == nil:
v, _ := strconv.ParseBool(s.SettingValue)
return v, nil
case IsErrSettingIsNotExist(err):
return defaultVal, nil
default:
return false, err
}
v, _ := strconv.ParseBool(s.SettingValue)
return v
}

func GetSettingWithCacheBool(ctx context.Context, key string) bool {
s, _ := GetSettingWithCache(ctx, key)
func GetSettingWithCacheBool(ctx context.Context, key string, defaultVal bool) bool {
s, _ := GetSettingWithCache(ctx, key, strconv.FormatBool(defaultVal))
v, _ := strconv.ParseBool(s)
return v
}
Expand Down Expand Up @@ -259,52 +266,41 @@ var (
)

func Init(ctx context.Context) error {
var disableGravatar bool
disableGravatarSetting, err := GetSetting(ctx, KeyPictureDisableGravatar)
if IsErrSettingIsNotExist(err) {
disableGravatar = setting_module.GetDefaultDisableGravatar()
disableGravatarSetting = &Setting{SettingValue: strconv.FormatBool(disableGravatar)}
} else if err != nil {
disableGravatar, err := GetSettingBool(ctx, KeyPictureDisableGravatar, setting_module.GetDefaultDisableGravatar())
if err != nil {
return err
} else {
disableGravatar = disableGravatarSetting.GetValueBool()
}

var enableFederatedAvatar bool
enableFederatedAvatarSetting, err := GetSetting(ctx, KeyPictureEnableFederatedAvatar)
if IsErrSettingIsNotExist(err) {
enableFederatedAvatar = setting_module.GetDefaultEnableFederatedAvatar(disableGravatar)
enableFederatedAvatarSetting = &Setting{SettingValue: strconv.FormatBool(enableFederatedAvatar)}
} else if err != nil {
enableFederatedAvatar, err := GetSettingBool(ctx, KeyPictureEnableFederatedAvatar, setting_module.GetDefaultEnableFederatedAvatar(disableGravatar))
if err != nil {
return err
} else {
enableFederatedAvatar = disableGravatarSetting.GetValueBool()
}

if setting_module.OfflineMode {
disableGravatar = true
enableFederatedAvatar = false
if !GetSettingBool(ctx, KeyPictureDisableGravatar) {
if !disableGravatar {
if err := SetSettingNoVersion(ctx, KeyPictureDisableGravatar, "true"); err != nil {
return fmt.Errorf("Failed to set setting %q: %w", KeyPictureDisableGravatar, err)
return fmt.Errorf("failed to set setting %q: %w", KeyPictureDisableGravatar, err)
}
}
if GetSettingBool(ctx, KeyPictureEnableFederatedAvatar) {
disableGravatar = true

if enableFederatedAvatar {
if err := SetSettingNoVersion(ctx, KeyPictureEnableFederatedAvatar, "false"); err != nil {
return fmt.Errorf("Failed to set setting %q: %w", KeyPictureEnableFederatedAvatar, err)
return fmt.Errorf("failed to set setting %q: %w", KeyPictureEnableFederatedAvatar, err)
}
}
enableFederatedAvatar = false
}

if enableFederatedAvatar || !disableGravatar {
var err error
GravatarSourceURL, err = url.Parse(setting_module.GravatarSource)
if err != nil {
return fmt.Errorf("Failed to parse Gravatar URL(%s): %w", setting_module.GravatarSource, err)
return fmt.Errorf("failed to parse Gravatar URL(%s): %w", setting_module.GravatarSource, err)
}
}

if GravatarSourceURL != nil && enableFederatedAvatarSetting.GetValueBool() {
if GravatarSourceURL != nil && enableFederatedAvatar {
LibravatarService = libravatar.New()
if GravatarSourceURL.Scheme == "https" {
LibravatarService.SetUseHTTPS(true)
Expand Down
4 changes: 3 additions & 1 deletion models/user/avatar.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
useLocalAvatar := false
autoGenerateAvatar := false

disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar)
disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar,
setting.GetDefaultDisableGravatar(),
)

switch {
case u.UseCustomAvatar:
Expand Down
58 changes: 18 additions & 40 deletions modules/repository/commits.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"code.gitea.io/gitea/models/avatars"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
Expand All @@ -34,42 +35,36 @@ type PushCommits struct {
HeadCommit *PushCommit
CompareURL string
Len int

avatars map[string]string
emailUsers map[string]*user_model.User
}

// NewPushCommits creates a new PushCommits object.
func NewPushCommits() *PushCommits {
return &PushCommits{
avatars: make(map[string]string),
emailUsers: make(map[string]*user_model.User),
}
return &PushCommits{}
}

// toAPIPayloadCommit converts a single PushCommit to an api.PayloadCommit object.
func (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, repoPath, repoLink string, commit *PushCommit) (*api.PayloadCommit, error) {
func (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repoPath, repoLink string, commit *PushCommit) (*api.PayloadCommit, error) {
var err error
authorUsername := ""
author, ok := pc.emailUsers[commit.AuthorEmail]
author, ok := emailUsers[commit.AuthorEmail]
if !ok {
author, err = user_model.GetUserByEmail(ctx, commit.AuthorEmail)
if err == nil {
authorUsername = author.Name
pc.emailUsers[commit.AuthorEmail] = author
emailUsers[commit.AuthorEmail] = author
}
} else {
authorUsername = author.Name
}

committerUsername := ""
committer, ok := pc.emailUsers[commit.CommitterEmail]
committer, ok := emailUsers[commit.CommitterEmail]
if !ok {
committer, err = user_model.GetUserByEmail(ctx, commit.CommitterEmail)
if err == nil {
// TODO: check errors other than email not found.
committerUsername = committer.Name
pc.emailUsers[commit.CommitterEmail] = committer
emailUsers[commit.CommitterEmail] = committer
}
} else {
committerUsername = committer.Name
Expand Down Expand Up @@ -107,11 +102,10 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi
commits := make([]*api.PayloadCommit, len(pc.Commits))
var headCommit *api.PayloadCommit

if pc.emailUsers == nil {
pc.emailUsers = make(map[string]*user_model.User)
}
emailUsers := make(map[string]*user_model.User)

for i, commit := range pc.Commits {
apiCommit, err := pc.toAPIPayloadCommit(ctx, repoPath, repoLink, commit)
apiCommit, err := pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, commit)
if err != nil {
return nil, nil, err
}
Expand All @@ -123,7 +117,7 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi
}
if pc.HeadCommit != nil && headCommit == nil {
var err error
headCommit, err = pc.toAPIPayloadCommit(ctx, repoPath, repoLink, pc.HeadCommit)
headCommit, err = pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, pc.HeadCommit)
if err != nil {
return nil, nil, err
}
Expand All @@ -134,35 +128,21 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi
// AvatarLink tries to match user in database with e-mail
// in order to show custom avatar, and falls back to general avatar link.
func (pc *PushCommits) AvatarLink(ctx context.Context, email string) string {
if pc.avatars == nil {
pc.avatars = make(map[string]string)
}
avatar, ok := pc.avatars[email]
if ok {
return avatar
}

size := avatars.DefaultAvatarPixelSize * setting.Avatar.RenderedSizeFactor

u, ok := pc.emailUsers[email]
if !ok {
var err error
u, err = user_model.GetUserByEmail(ctx, email)
v, _ := cache.GetWithContextCache(ctx, "push_commits", email, func() (string, error) {
u, err := user_model.GetUserByEmail(ctx, email)
if err != nil {
pc.avatars[email] = avatars.GenerateEmailAvatarFastLink(ctx, email, size)
if !user_model.IsErrUserNotExist(err) {
log.Error("GetUserByEmail: %v", err)
return ""
return "", err
}
} else {
pc.emailUsers[email] = u
return avatars.GenerateEmailAvatarFastLink(ctx, email, size), nil
}
}
if u != nil {
pc.avatars[email] = u.AvatarLinkWithSize(ctx, size)
}
return u.AvatarLinkWithSize(ctx, size), nil
})

return pc.avatars[email]
return v
}

// CommitToPushCommit transforms a git.Commit to PushCommit type.
Expand All @@ -189,7 +169,5 @@ func GitToPushCommits(gitCommits []*git.Commit) *PushCommits {
HeadCommit: nil,
CompareURL: "",
Len: len(commits),
avatars: make(map[string]string),
emailUsers: make(map[string]*user_model.User),
}
}
8 changes: 3 additions & 5 deletions modules/repository/commits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,9 @@ func TestPushCommits_ToAPIPayloadCommits(t *testing.T) {
assert.EqualValues(t, []string{"readme.md"}, headCommit.Modified)
}

func enableGravatar(t *testing.T) {
err := system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureDisableGravatar, "false")
assert.NoError(t, err)
func initGravatarSource(t *testing.T) {
setting.GravatarSource = "https://secure.gravatar.com/avatar"
err = system_model.Init(db.DefaultContext)
err := system_model.Init(db.DefaultContext)
assert.NoError(t, err)
}

Expand All @@ -134,7 +132,7 @@ func TestPushCommits_AvatarLink(t *testing.T) {
},
}

enableGravatar(t)
initGravatarSource(t)

assert.Equal(t,
"https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?d=identicon&s="+strconv.Itoa(28*setting.Avatar.RenderedSizeFactor),
Expand Down
2 changes: 1 addition & 1 deletion modules/setting/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func loadSessionFrom(rootCfg ConfigProvider) {
}
SessionConfig.CookieName = sec.Key("COOKIE_NAME").MustString("i_like_gitea")
SessionConfig.CookiePath = AppSubURL + "/" // there was a bug, old code only set CookePath=AppSubURL, no trailing slash
SessionConfig.Secure = sec.Key("COOKIE_SECURE").MustBool(false)
SessionConfig.Secure = sec.Key("COOKIE_SECURE").MustBool(strings.HasPrefix(strings.ToLower(AppURL), "https://"))
SessionConfig.Gclifetime = sec.Key("GC_INTERVAL_TIME").MustInt64(86400)
SessionConfig.Maxlifetime = sec.Key("SESSION_LIFE_TIME").MustInt64(86400)
SessionConfig.Domain = sec.Key("DOMAIN").String()
Expand Down
Loading

0 comments on commit 85b3127

Please sign in to comment.