mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-17 19:42:55 +02:00
rewrite
This commit is contained in:
parent
d92ec015c4
commit
fed3ade254
@ -1,84 +0,0 @@
|
||||
- user_id: 1
|
||||
actions: failureonly
|
||||
- user_id: 2
|
||||
actions: failureonly
|
||||
- user_id: 3
|
||||
actions: failureonly
|
||||
- user_id: 4
|
||||
actions: failureonly
|
||||
- user_id: 5
|
||||
actions: failureonly
|
||||
- user_id: 6
|
||||
actions: failureonly
|
||||
- user_id: 7
|
||||
actions: failureonly
|
||||
- user_id: 8
|
||||
actions: failureonly
|
||||
- user_id: 9
|
||||
actions: failureonly
|
||||
- user_id: 10
|
||||
actions: failureonly
|
||||
- user_id: 11
|
||||
actions: failureonly
|
||||
- user_id: 12
|
||||
actions: failureonly
|
||||
- user_id: 13
|
||||
actions: failureonly
|
||||
- user_id: 14
|
||||
actions: failureonly
|
||||
- user_id: 15
|
||||
actions: failureonly
|
||||
- user_id: 16
|
||||
actions: failureonly
|
||||
- user_id: 17
|
||||
actions: failureonly
|
||||
- user_id: 18
|
||||
actions: failureonly
|
||||
- user_id: 19
|
||||
actions: failureonly
|
||||
- user_id: 20
|
||||
actions: failureonly
|
||||
- user_id: 21
|
||||
actions: failureonly
|
||||
- user_id: 22
|
||||
actions: failureonly
|
||||
- user_id: 23
|
||||
actions: failureonly
|
||||
- user_id: 24
|
||||
actions: failureonly
|
||||
- user_id: 25
|
||||
actions: failureonly
|
||||
- user_id: 26
|
||||
actions: failureonly
|
||||
- user_id: 27
|
||||
actions: failureonly
|
||||
- user_id: 28
|
||||
actions: failureonly
|
||||
- user_id: 29
|
||||
actions: failureonly
|
||||
- user_id: 30
|
||||
actions: failureonly
|
||||
- user_id: 31
|
||||
actions: failureonly
|
||||
- user_id: 32
|
||||
actions: failureonly
|
||||
- user_id: 33
|
||||
actions: failureonly
|
||||
- user_id: 34
|
||||
actions: failureonly
|
||||
- user_id: 35
|
||||
actions: failureonly
|
||||
- user_id: 36
|
||||
actions: failureonly
|
||||
- user_id: 37
|
||||
actions: failureonly
|
||||
- user_id: 38
|
||||
actions: failureonly
|
||||
- user_id: 39
|
||||
actions: failureonly
|
||||
- user_id: 40
|
||||
actions: failureonly
|
||||
- user_id: 41
|
||||
actions: failureonly
|
||||
- user_id: 42
|
||||
actions: failureonly
|
@ -382,7 +382,6 @@ func prepareMigrationTasks() []*migration {
|
||||
newMigration(318, "Add anonymous_access_mode for repo_unit", v1_24.AddRepoUnitAnonymousAccessMode),
|
||||
newMigration(319, "Add ExclusiveOrder to Label table", v1_24.AddExclusiveOrderColumnToLabelTable),
|
||||
newMigration(320, "Migrate two_factor_policy to login_source table", v1_24.MigrateSkipTwoFactor),
|
||||
newMigration(321, "Add new table for fine-grained notification settings", v1_24.AddFineGrainedActionsNotificationSettings),
|
||||
}
|
||||
return preparedMigrations
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_24
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type NotificationSettings struct {
|
||||
UserID int64 `xorm:"pk"`
|
||||
Actions string `xorm:"NOT NULL DEFAULT 'failureonly'"`
|
||||
}
|
||||
|
||||
func (*NotificationSettings) TableName() string {
|
||||
return "user_notification_settings"
|
||||
}
|
||||
|
||||
func AddFineGrainedActionsNotificationSettings(x *xorm.Engine) error {
|
||||
if err := x.Sync(&NotificationSettings{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
settings := make([]NotificationSettings, 0, 100)
|
||||
|
||||
type User struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
}
|
||||
|
||||
if err := db.Iterate(context.Background(), nil, func(ctx context.Context, user *User) error {
|
||||
settings = append(settings, NotificationSettings{
|
||||
UserID: user.ID,
|
||||
Actions: user_model.NotificationGiteaActionsFailureOnly,
|
||||
})
|
||||
if len(settings) >= 100 {
|
||||
_, err := x.Insert(&settings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settings = settings[:0]
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(settings) > 0 {
|
||||
if _, err := x.Insert(&settings); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
11
models/user/email_notification.go
Normal file
11
models/user/email_notification.go
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user
|
||||
|
||||
// setting values
|
||||
const (
|
||||
EmailNotificationGiteaActionsAll = "all"
|
||||
EmailNotificationGiteaActionsFailureOnly = "failureonly" // Default for actions email preference
|
||||
EmailNotificationGiteaActionsDisabled = "disabled"
|
||||
)
|
34
models/user/email_notification_test.go
Normal file
34
models/user/email_notification_test.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNotificationSettings(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
u := unittest.AssertExistsAndLoadBean(t, &User{ID: 1})
|
||||
|
||||
assert.NoError(t, SetUserSetting(db.DefaultContext, u.ID, SettingsEmailNotificationGiteaActions, EmailNotificationGiteaActionsAll))
|
||||
settings, err := GetSetting(db.DefaultContext, u.ID, SettingsEmailNotificationGiteaActions)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, EmailNotificationGiteaActionsAll, settings)
|
||||
|
||||
assert.NoError(t, SetUserSetting(db.DefaultContext, u.ID, SettingsEmailNotificationGiteaActions, EmailNotificationGiteaActionsDisabled))
|
||||
settings, err = GetSetting(db.DefaultContext, u.ID, SettingsEmailNotificationGiteaActions)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, EmailNotificationGiteaActionsDisabled, settings)
|
||||
|
||||
assert.NoError(t, SetUserSetting(db.DefaultContext, u.ID, SettingsEmailNotificationGiteaActions, EmailNotificationGiteaActionsFailureOnly))
|
||||
settings, err = GetSetting(db.DefaultContext, u.ID, SettingsEmailNotificationGiteaActions)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, EmailNotificationGiteaActionsFailureOnly, settings)
|
||||
}
|
@ -21,4 +21,6 @@ const (
|
||||
SignupUserAgent = "signup.user_agent"
|
||||
|
||||
SettingsKeyCodeViewShowFileTree = "code_view.show_file_tree"
|
||||
|
||||
SettingsEmailNotificationGiteaActions = "email_notifications.actions"
|
||||
)
|
||||
|
@ -798,10 +798,7 @@ func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, o
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Insert(ctx, &NotificationSettings{
|
||||
UserID: u.ID,
|
||||
Actions: NotificationGiteaActionsFailureOnly,
|
||||
}); err != nil {
|
||||
if err := SetUserSetting(ctx, u.ID, SettingsEmailNotificationGiteaActions, EmailNotificationGiteaActionsFailureOnly); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
)
|
||||
|
||||
// Actions email preference
|
||||
const (
|
||||
NotificationGiteaActionsAll = "all"
|
||||
NotificationGiteaActionsFailureOnly = "failureonly"
|
||||
NotificationGiteaActionsDisabled = "disabled"
|
||||
)
|
||||
|
||||
type NotificationSettings struct {
|
||||
UserID int64 `xorm:"pk"`
|
||||
User *User `xorm:"-"`
|
||||
Actions string `xorm:"NOT NULL DEFAULT 'failureonly'"`
|
||||
}
|
||||
|
||||
func (NotificationSettings) TableName() string {
|
||||
return "user_notification_settings"
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(NotificationSettings))
|
||||
}
|
||||
|
||||
// GetUserNotificationSettings returns a user's fine-grained notification preference
|
||||
func GetUserNotificationSettings(ctx context.Context, userID int64) (*NotificationSettings, error) {
|
||||
settings := &NotificationSettings{}
|
||||
if has, err := db.GetEngine(ctx).Where("user_id=?", userID).Get(settings); err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, nil
|
||||
}
|
||||
user, err := GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
settings.User = user
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
func UpdateUserNotificationSettings(ctx context.Context, settings *NotificationSettings) error {
|
||||
_, err := db.GetEngine(ctx).Where("user_id = ?", settings.UserID).
|
||||
Update(&NotificationSettings{
|
||||
Actions: settings.Actions,
|
||||
})
|
||||
return err
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUserNotificationSettings(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
settings, err := GetUserNotificationSettings(db.DefaultContext, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, settings.User)
|
||||
assert.Equal(t, settings.User.ID, settings.UserID)
|
||||
assert.Equal(t, NotificationGiteaActionsFailureOnly, settings.Actions)
|
||||
|
||||
assert.NoError(t, UpdateUserNotificationSettings(db.DefaultContext, &NotificationSettings{
|
||||
UserID: 1,
|
||||
Actions: NotificationGiteaActionsAll,
|
||||
}))
|
||||
settings, err = GetUserNotificationSettings(db.DefaultContext, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, settings.User)
|
||||
assert.Equal(t, settings.User.ID, settings.UserID)
|
||||
assert.Equal(t, NotificationGiteaActionsAll, settings.Actions)
|
||||
|
||||
assert.NoError(t, UpdateUserNotificationSettings(db.DefaultContext, &NotificationSettings{
|
||||
UserID: 1,
|
||||
Actions: NotificationGiteaActionsDisabled,
|
||||
}))
|
||||
settings, err = GetUserNotificationSettings(db.DefaultContext, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, settings.User)
|
||||
assert.Equal(t, settings.User.ID, settings.UserID)
|
||||
assert.Equal(t, NotificationGiteaActionsDisabled, settings.Actions)
|
||||
}
|
@ -30,12 +30,18 @@ func Notifications(ctx *context.Context) {
|
||||
ctx.Data["PageIsSettingsNotifications"] = true
|
||||
ctx.Data["EmailNotificationsPreference"] = ctx.Doer.EmailNotificationsPreference
|
||||
|
||||
fineGrainedPreference, err := user_model.GetUserNotificationSettings(ctx, ctx.Doer.ID)
|
||||
fineGrainedPreference, err := user_model.GetSettings(ctx, ctx.Doer.ID, []string{
|
||||
user_model.SettingsEmailNotificationGiteaActions,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUserNotificationSettings", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["ActionsEmailNotificationsPreference"] = fineGrainedPreference.Actions
|
||||
actionsNotify := fineGrainedPreference[user_model.SettingsEmailNotificationGiteaActions].SettingValue
|
||||
if actionsNotify == "" {
|
||||
actionsNotify = user_model.EmailNotificationGiteaActionsFailureOnly
|
||||
}
|
||||
ctx.Data["ActionsEmailNotificationsPreference"] = actionsNotify
|
||||
|
||||
ctx.HTML(http.StatusOK, tplSettingsNotifications)
|
||||
}
|
||||
@ -77,19 +83,16 @@ func NotificationsActionsEmailPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
preference := ctx.FormString("preference")
|
||||
if !(preference == user_model.NotificationGiteaActionsAll ||
|
||||
preference == user_model.NotificationGiteaActionsDisabled ||
|
||||
preference == user_model.NotificationGiteaActionsFailureOnly) {
|
||||
if !(preference == user_model.EmailNotificationGiteaActionsAll ||
|
||||
preference == user_model.EmailNotificationGiteaActionsDisabled ||
|
||||
preference == user_model.EmailNotificationGiteaActionsFailureOnly) {
|
||||
log.Error("Actions Email notifications preference change returned unrecognized option %s: %s", preference, ctx.Doer.Name)
|
||||
ctx.ServerError("NotificationsActionsEmailPost", errors.New("option unrecognized"))
|
||||
return
|
||||
}
|
||||
opts := &user.UpdateNotificationSettingsOptions{
|
||||
Actions: optional.Some(preference),
|
||||
}
|
||||
if err := user.UpdateNotificationSettings(ctx, ctx.Doer.ID, opts); err != nil {
|
||||
if err := user_model.SetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsEmailNotificationGiteaActions, preference); err != nil {
|
||||
log.Error("Cannot set actions email notifications preference: %v", err)
|
||||
ctx.ServerError("UpdateNotificationSettings", err)
|
||||
ctx.ServerError("SetUserSetting", err)
|
||||
return
|
||||
}
|
||||
log.Trace("Actions email notifications preference made %s: %s", preference, ctx.Doer.Name)
|
||||
|
@ -149,18 +149,19 @@ func SendActionsWorkflowRunStatusEmail(ctx context.Context, sender *user_model.U
|
||||
recipients := make([]*user_model.User, 0)
|
||||
|
||||
if !sender.IsGiteaActions() && !sender.IsGhost() && sender.IsMailable() {
|
||||
notifyPref, err := user_model.GetUserNotificationSettings(ctx, sender.ID)
|
||||
notifyPref, err := user_model.GetUserSetting(ctx, sender.ID,
|
||||
user_model.SettingsEmailNotificationGiteaActions, user_model.EmailNotificationGiteaActionsFailureOnly)
|
||||
if err != nil {
|
||||
log.Error("GetUserNotificationSettings: %v", err)
|
||||
log.Error("GetUserSetting: %v", err)
|
||||
return
|
||||
}
|
||||
if run.Status.IsSuccess() {
|
||||
if notifyPref.Actions == user_model.NotificationGiteaActionsAll {
|
||||
if notifyPref == user_model.EmailNotificationGiteaActionsAll {
|
||||
recipients = append(recipients, sender)
|
||||
}
|
||||
sendActionsWorkflowRunStatusEmail(ctx, repo, run, sender, recipients)
|
||||
return
|
||||
} else if notifyPref.Actions != user_model.NotificationGiteaActionsDisabled {
|
||||
} else if notifyPref != user_model.EmailNotificationGiteaActionsDisabled {
|
||||
recipients = append(recipients, sender)
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,6 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
|
||||
&user_model.Blocking{BlockerID: u.ID},
|
||||
&user_model.Blocking{BlockeeID: u.ID},
|
||||
&actions_model.ActionRunnerToken{OwnerID: u.ID},
|
||||
&user_model.NotificationSettings{UserID: u.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %w", err)
|
||||
}
|
||||
|
@ -244,18 +244,3 @@ func UpdateAuth(ctx context.Context, u *user_model.User, opts *UpdateAuthOptions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateNotificationSettingsOptions struct {
|
||||
Actions optional.Option[string]
|
||||
}
|
||||
|
||||
func UpdateNotificationSettings(ctx context.Context, userID int64, opts *UpdateNotificationSettingsOptions) error {
|
||||
settings := &user_model.NotificationSettings{
|
||||
UserID: userID,
|
||||
}
|
||||
if opts.Actions.Has() {
|
||||
settings.Actions = opts.Actions.Value()
|
||||
}
|
||||
|
||||
return user_model.UpdateUserNotificationSettings(ctx, settings)
|
||||
}
|
||||
|
@ -122,30 +122,3 @@ func TestUpdateAuth(t *testing.T) {
|
||||
Password: optional.Some("aaaa"),
|
||||
}), password_module.ErrMinLength)
|
||||
}
|
||||
|
||||
func TestUpdateNotificationSettings(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
settings := &user_model.NotificationSettings{UserID: 2}
|
||||
exists, err := db.GetEngine(db.DefaultContext).Get(settings)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exists)
|
||||
|
||||
assert.NoError(t, UpdateNotificationSettings(db.DefaultContext, settings.UserID, &UpdateNotificationSettingsOptions{
|
||||
Actions: optional.Some(user_model.NotificationGiteaActionsAll),
|
||||
}))
|
||||
settings, err = user_model.GetUserNotificationSettings(db.DefaultContext, settings.UserID)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, settings)
|
||||
assert.Equal(t, user_model.NotificationGiteaActionsAll, settings.Actions)
|
||||
assert.NotEqual(t, user_model.NotificationGiteaActionsFailureOnly, settings.Actions)
|
||||
|
||||
assert.NoError(t, UpdateNotificationSettings(db.DefaultContext, settings.UserID, &UpdateNotificationSettingsOptions{
|
||||
Actions: optional.Some(user_model.NotificationGiteaActionsDisabled),
|
||||
}))
|
||||
settings, err = user_model.GetUserNotificationSettings(db.DefaultContext, settings.UserID)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, settings)
|
||||
assert.Equal(t, user_model.NotificationGiteaActionsDisabled, settings.Actions)
|
||||
assert.NotEqual(t, user_model.NotificationGiteaActionsFailureOnly, settings.Actions)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user