diff --git a/models/system/setting.go b/models/system/setting.go
index 1ae6f5c652836..507d23cff6bbf 100644
--- a/models/system/setting.go
+++ b/models/system/setting.go
@@ -115,24 +115,26 @@ func (d *dbConfigCachedGetter) GetValue(ctx context.Context, key string) (v stri
func (d *dbConfigCachedGetter) GetRevision(ctx context.Context) int {
d.mu.RLock()
- defer d.mu.RUnlock()
- if time.Since(d.cacheTime) < time.Second {
- return d.revision
+ cachedDuration := time.Since(d.cacheTime)
+ cachedRevision := d.revision
+ d.mu.RUnlock()
+
+ if cachedDuration < time.Second {
+ return cachedRevision
}
+
+ d.mu.Lock()
+ defer d.mu.Unlock()
if GetRevision(ctx) != d.revision {
- d.mu.RUnlock()
- d.mu.Lock()
rev, set, err := GetAllSettings(ctx)
if err != nil {
log.Error("Unable to get all settings: %v", err)
} else {
- d.cacheTime = time.Now()
d.revision = rev
d.settings = set
}
- d.mu.Unlock()
- d.mu.RLock()
}
+ d.cacheTime = time.Now()
return d.revision
}
diff --git a/modules/setting/database.go b/modules/setting/database.go
index aa42f506bc51b..761e767e8f5f7 100644
--- a/modules/setting/database.go
+++ b/modules/setting/database.go
@@ -109,7 +109,7 @@ func DBConnStr() (string, error) {
connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s",
Database.User, Database.Passwd, connType, Database.Host, Database.Name, paramSep, Database.MysqlCharset, tls)
case "postgres":
- connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, paramSep, Database.SSLMode)
+ connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, Database.SSLMode)
case "mssql":
host, port := ParseMSSQLHostPort(Database.Host)
connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, Database.Name, Database.User, Database.Passwd)
@@ -157,7 +157,8 @@ func parsePostgreSQLHostPort(info string) (host, port string) {
return host, port
}
-func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) {
+func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbsslMode string) (connStr string) {
+ dbName, dbParam, _ := strings.Cut(dbName, "?")
host, port := parsePostgreSQLHostPort(dbHost)
connURL := url.URL{
Scheme: "postgres",
diff --git a/modules/setting/database_test.go b/modules/setting/database_test.go
index 85271c36cb388..1d5b416504b18 100644
--- a/modules/setting/database_test.go
+++ b/modules/setting/database_test.go
@@ -59,38 +59,39 @@ func Test_parsePostgreSQLHostPort(t *testing.T) {
func Test_getPostgreSQLConnectionString(t *testing.T) {
tests := []struct {
Host string
- Port string
User string
Passwd string
Name string
- Param string
SSLMode string
Output string
}{
{
Host: "/tmp/pg.sock",
- Port: "4321",
User: "testuser",
Passwd: "space space !#$%^^%^```-=?=",
Name: "gitea",
- Param: "",
SSLMode: "false",
Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/gitea?host=%2Ftmp%2Fpg.sock&sslmode=false",
},
{
Host: "localhost",
- Port: "1234",
User: "pgsqlusername",
Passwd: "I love Gitea!",
Name: "gitea",
- Param: "",
SSLMode: "true",
Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/gitea?sslmode=true",
},
+ {
+ Host: "localhost:1234",
+ User: "user",
+ Passwd: "pass",
+ Name: "gitea?param=1",
+ Output: "postgres://user:pass@localhost:1234/gitea?param=1&sslmode=",
+ },
}
for _, test := range tests {
- connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode)
+ connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.SSLMode)
assert.Equal(t, test.Output, connStr)
}
}
diff --git a/services/webhook/dingtalk_test.go b/services/webhook/dingtalk_test.go
index 7289c751f3845..a03fa46f1458f 100644
--- a/services/webhook/dingtalk_test.go
+++ b/services/webhook/dingtalk_test.go
@@ -188,6 +188,21 @@ func TestDingTalkPayload(t *testing.T) {
assert.Equal(t, "http://localhost:3000/test/repo", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(DingtalkPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.NotNil(t, pl)
+ require.IsType(t, &DingtalkPayload{}, pl)
+
+ assert.Equal(t, "Package created: GiteaContainer:latest by user1", pl.(*DingtalkPayload).ActionCard.Text)
+ assert.Equal(t, "Package created: GiteaContainer:latest by user1", pl.(*DingtalkPayload).ActionCard.Title)
+ assert.Equal(t, "view package", pl.(*DingtalkPayload).ActionCard.SingleTitle)
+ assert.Equal(t, "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()
diff --git a/services/webhook/discord_test.go b/services/webhook/discord_test.go
index 6a276e9e874da..b567cbc395db1 100644
--- a/services/webhook/discord_test.go
+++ b/services/webhook/discord_test.go
@@ -211,6 +211,24 @@ func TestDiscordPayload(t *testing.T) {
assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL)
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(DiscordPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.NotNil(t, pl)
+ require.IsType(t, &DiscordPayload{}, pl)
+
+ assert.Len(t, pl.(*DiscordPayload).Embeds, 1)
+ assert.Equal(t, "Package created: GiteaContainer:latest", pl.(*DiscordPayload).Embeds[0].Title)
+ assert.Empty(t, pl.(*DiscordPayload).Embeds[0].Description)
+ assert.Equal(t, "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest", pl.(*DiscordPayload).Embeds[0].URL)
+ assert.Equal(t, p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.Name)
+ assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.URL)
+ assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL)
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()
diff --git a/services/webhook/feishu_test.go b/services/webhook/feishu_test.go
index a3182e82b09af..98bc50dedec87 100644
--- a/services/webhook/feishu_test.go
+++ b/services/webhook/feishu_test.go
@@ -144,6 +144,18 @@ func TestFeishuPayload(t *testing.T) {
assert.Equal(t, "[test/repo] Repository created", pl.(*FeishuPayload).Content.Text)
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(FeishuPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.NotNil(t, pl)
+ require.IsType(t, &FeishuPayload{}, pl)
+
+ assert.Equal(t, "Package created: GiteaContainer:latest by user1", pl.(*FeishuPayload).Content.Text)
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()
diff --git a/services/webhook/general_test.go b/services/webhook/general_test.go
index a9a8c6b5212c1..41bac3fd04d23 100644
--- a/services/webhook/general_test.go
+++ b/services/webhook/general_test.go
@@ -303,6 +303,36 @@ func repositoryTestPayload() *api.RepositoryPayload {
}
}
+func packageTestPayload() *api.PackagePayload {
+ return &api.PackagePayload{
+ Action: api.HookPackageCreated,
+ Sender: &api.User{
+ UserName: "user1",
+ AvatarURL: "http://localhost:3000/user1/avatar",
+ },
+ Repository: nil,
+ Organization: &api.User{
+ UserName: "org1",
+ AvatarURL: "http://localhost:3000/org1/avatar",
+ },
+ Package: &api.Package{
+ Owner: &api.User{
+ UserName: "user1",
+ AvatarURL: "http://localhost:3000/user1/avatar",
+ },
+ Repository: nil,
+ Creator: &api.User{
+ UserName: "user1",
+ AvatarURL: "http://localhost:3000/user1/avatar",
+ },
+ Type: "container",
+ Name: "GiteaContainer",
+ Version: "latest",
+ HTMLURL: "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest",
+ },
+ }
+}
+
func TestGetIssuesPayloadInfo(t *testing.T) {
p := issueTestPayload()
diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go
index ab7e6b72c25f1..602d16ef39b0e 100644
--- a/services/webhook/matrix.go
+++ b/services/webhook/matrix.go
@@ -212,14 +212,14 @@ func (m *MatrixPayload) Repository(p *api.RepositoryPayload) (api.Payloader, err
func (m *MatrixPayload) Package(p *api.PackagePayload) (api.Payloader, error) {
senderLink := MatrixLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
- repoLink := MatrixLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
+ packageLink := MatrixLinkFormatter(p.Package.HTMLURL, p.Package.Name)
var text string
switch p.Action {
case api.HookPackageCreated:
- text = fmt.Sprintf("[%s] Package published by %s", repoLink, senderLink)
+ text = fmt.Sprintf("[%s] Package published by %s", packageLink, senderLink)
case api.HookPackageDeleted:
- text = fmt.Sprintf("[%s] Package deleted by %s", repoLink, senderLink)
+ text = fmt.Sprintf("[%s] Package deleted by %s", packageLink, senderLink)
}
return getMatrixPayload(text, nil, m.MsgType), nil
diff --git a/services/webhook/matrix_test.go b/services/webhook/matrix_test.go
index 8c710942280fa..99a22fbd7eb3a 100644
--- a/services/webhook/matrix_test.go
+++ b/services/webhook/matrix_test.go
@@ -155,6 +155,19 @@ func TestMatrixPayload(t *testing.T) {
assert.Equal(t, `[test/repo] Repository created by user1`, pl.(*MatrixPayload).FormattedBody)
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(MatrixPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.NotNil(t, pl)
+ require.IsType(t, &MatrixPayload{}, pl)
+
+ assert.Equal(t, `[[GiteaContainer](http://localhost:3000/user1/-/packages/container/GiteaContainer/latest)] Package published by [user1](https://try.gitea.io/user1)`, pl.(*MatrixPayload).Body)
+ assert.Equal(t, `[GiteaContainer] Package published by user1`, pl.(*MatrixPayload).FormattedBody)
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()
diff --git a/services/webhook/msteams.go b/services/webhook/msteams.go
index f58da3fe1cd6f..37810b4cd3959 100644
--- a/services/webhook/msteams.go
+++ b/services/webhook/msteams.go
@@ -316,11 +316,12 @@ func GetMSTeamsPayload(p api.Payloader, event webhook_module.HookEventType, _ st
}
func createMSTeamsPayload(r *api.Repository, s *api.User, title, text, actionTarget string, color int, fact *MSTeamsFact) *MSTeamsPayload {
- facts := []MSTeamsFact{
- {
+ facts := make([]MSTeamsFact, 0, 2)
+ if r != nil {
+ facts = append(facts, MSTeamsFact{
Name: "Repository:",
Value: r.FullName,
- },
+ })
}
if fact != nil {
facts = append(facts, *fact)
diff --git a/services/webhook/msteams_test.go b/services/webhook/msteams_test.go
index 990a535df5c1a..8d1aed604086e 100644
--- a/services/webhook/msteams_test.go
+++ b/services/webhook/msteams_test.go
@@ -329,6 +329,33 @@ func TestMSTeamsPayload(t *testing.T) {
assert.Equal(t, "http://localhost:3000/test/repo", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI)
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(MSTeamsPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.NotNil(t, pl)
+ require.IsType(t, &MSTeamsPayload{}, pl)
+
+ assert.Equal(t, "Package created: GiteaContainer:latest", pl.(*MSTeamsPayload).Title)
+ assert.Equal(t, "Package created: GiteaContainer:latest", pl.(*MSTeamsPayload).Summary)
+ assert.Len(t, pl.(*MSTeamsPayload).Sections, 1)
+ assert.Equal(t, "user1", pl.(*MSTeamsPayload).Sections[0].ActivitySubtitle)
+ assert.Empty(t, pl.(*MSTeamsPayload).Sections[0].Text)
+ assert.Len(t, pl.(*MSTeamsPayload).Sections[0].Facts, 1)
+ for _, fact := range pl.(*MSTeamsPayload).Sections[0].Facts {
+ if fact.Name == "Package:" {
+ assert.Equal(t, p.Package.Name, fact.Value)
+ } else {
+ t.Fail()
+ }
+ }
+ assert.Len(t, pl.(*MSTeamsPayload).PotentialAction, 1)
+ assert.Len(t, pl.(*MSTeamsPayload).PotentialAction[0].Targets, 1)
+ assert.Equal(t, "http://localhost:3000/user1/-/packages/container/GiteaContainer/latest", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI)
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()
diff --git a/services/webhook/packagist_test.go b/services/webhook/packagist_test.go
index 932b56fe9b9a1..26d01b0555ddc 100644
--- a/services/webhook/packagist_test.go
+++ b/services/webhook/packagist_test.go
@@ -115,6 +115,15 @@ func TestPackagistPayload(t *testing.T) {
require.Nil(t, pl)
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(PackagistPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.Nil(t, pl)
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()
diff --git a/services/webhook/slack_test.go b/services/webhook/slack_test.go
index d9828f374f0dd..b1340963e2301 100644
--- a/services/webhook/slack_test.go
+++ b/services/webhook/slack_test.go
@@ -144,6 +144,18 @@ func TestSlackPayload(t *testing.T) {
assert.Equal(t, "[] Repository created by ", pl.(*SlackPayload).Text)
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(SlackPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.NotNil(t, pl)
+ require.IsType(t, &SlackPayload{}, pl)
+
+ assert.Equal(t, "Package created: by ", pl.(*SlackPayload).Text)
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()
diff --git a/services/webhook/telegram_test.go b/services/webhook/telegram_test.go
index b42b0ccda8847..5b9927d0571e2 100644
--- a/services/webhook/telegram_test.go
+++ b/services/webhook/telegram_test.go
@@ -144,6 +144,18 @@ func TestTelegramPayload(t *testing.T) {
assert.Equal(t, `[test/repo] Repository created`, pl.(*TelegramPayload).Message)
})
+ t.Run("Package", func(t *testing.T) {
+ p := packageTestPayload()
+
+ d := new(TelegramPayload)
+ pl, err := d.Package(p)
+ require.NoError(t, err)
+ require.NotNil(t, pl)
+ require.IsType(t, &TelegramPayload{}, pl)
+
+ assert.Equal(t, `Package created: GiteaContainer:latest by user1`, pl.(*TelegramPayload).Message)
+ })
+
t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()