mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-19 23:38:29 +02:00
DATABASE
This commit is contained in:
parent
7a635ddf97
commit
540c3f00eb
84
models/fixtures/user_notification_settings.yml
Normal file
84
models/fixtures/user_notification_settings.yml
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
- 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,6 +382,7 @@ func prepareMigrationTasks() []*migration {
|
|||||||
newMigration(318, "Add anonymous_access_mode for repo_unit", v1_24.AddRepoUnitAnonymousAccessMode),
|
newMigration(318, "Add anonymous_access_mode for repo_unit", v1_24.AddRepoUnitAnonymousAccessMode),
|
||||||
newMigration(319, "Add ExclusiveOrder to Label table", v1_24.AddExclusiveOrderColumnToLabelTable),
|
newMigration(319, "Add ExclusiveOrder to Label table", v1_24.AddExclusiveOrderColumnToLabelTable),
|
||||||
newMigration(320, "Migrate two_factor_policy to login_source table", v1_24.MigrateSkipTwoFactor),
|
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
|
return preparedMigrations
|
||||||
}
|
}
|
||||||
|
59
models/migrations/v1_24/v321.go
Normal file
59
models/migrations/v1_24/v321.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// 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.NotificationActionsFailureOnly,
|
||||||
|
})
|
||||||
|
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
|
||||||
|
}
|
@ -798,6 +798,12 @@ func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, o
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := db.Insert(ctx, &NotificationSettings{
|
||||||
|
UserID: u.ID,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
54
models/user/user_notification.go
Normal file
54
models/user/user_notification.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NotificationActionsAll = "all"
|
||||||
|
NotificationActionsFailureOnly = "failureonly"
|
||||||
|
NotificationActionsDisabled = "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
|
||||||
|
}
|
37
models/user/user_notification_test.go
Normal file
37
models/user/user_notification_test.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 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.Equal(t, NotificationActionsFailureOnly, settings.Actions)
|
||||||
|
|
||||||
|
assert.NoError(t, UpdateUserNotificationSettings(db.DefaultContext, &NotificationSettings{
|
||||||
|
UserID: 1,
|
||||||
|
Actions: NotificationActionsAll,
|
||||||
|
}))
|
||||||
|
settings, err = GetUserNotificationSettings(db.DefaultContext, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, NotificationActionsAll, settings.Actions)
|
||||||
|
|
||||||
|
assert.NoError(t, UpdateUserNotificationSettings(db.DefaultContext, &NotificationSettings{
|
||||||
|
UserID: 1,
|
||||||
|
Actions: NotificationActionsDisabled,
|
||||||
|
}))
|
||||||
|
settings, err = GetUserNotificationSettings(db.DefaultContext, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, NotificationActionsDisabled, settings.Actions)
|
||||||
|
}
|
@ -95,6 +95,7 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
|
|||||||
&user_model.Blocking{BlockerID: u.ID},
|
&user_model.Blocking{BlockerID: u.ID},
|
||||||
&user_model.Blocking{BlockeeID: u.ID},
|
&user_model.Blocking{BlockeeID: u.ID},
|
||||||
&actions_model.ActionRunnerToken{OwnerID: u.ID},
|
&actions_model.ActionRunnerToken{OwnerID: u.ID},
|
||||||
|
&user_model.NotificationSettings{UserID: u.ID},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("deleteBeans: %w", err)
|
return fmt.Errorf("deleteBeans: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -244,3 +244,15 @@ func UpdateAuth(ctx context.Context, u *user_model.User, opts *UpdateAuthOptions
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateNotificationSettingsOptions struct {
|
||||||
|
Actions optional.Option[string]
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateNotificationSettings(ctx context.Context, settings *user_model.NotificationSettings, opts *UpdateNotificationSettingsOptions) error {
|
||||||
|
if opts.Actions.Has() {
|
||||||
|
settings.Actions = opts.Actions.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
return user_model.UpdateUserNotificationSettings(ctx, settings)
|
||||||
|
}
|
||||||
|
@ -122,3 +122,25 @@ func TestUpdateAuth(t *testing.T) {
|
|||||||
Password: optional.Some("aaaa"),
|
Password: optional.Some("aaaa"),
|
||||||
}), password_module.ErrMinLength)
|
}), 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)
|
||||||
|
settingsCopy := *settings
|
||||||
|
|
||||||
|
assert.NoError(t, UpdateNotificationSettings(db.DefaultContext, settings, &UpdateNotificationSettingsOptions{
|
||||||
|
Actions: optional.Some(user_model.NotificationActionsAll),
|
||||||
|
}))
|
||||||
|
assert.Equal(t, user_model.NotificationActionsAll, settings.Actions)
|
||||||
|
assert.NotEqual(t, settingsCopy.Actions, settings.Actions)
|
||||||
|
|
||||||
|
assert.NoError(t, UpdateNotificationSettings(db.DefaultContext, settings, &UpdateNotificationSettingsOptions{
|
||||||
|
Actions: optional.Some(user_model.NotificationActionsDisabled),
|
||||||
|
}))
|
||||||
|
assert.Equal(t, user_model.NotificationActionsDisabled, settings.Actions)
|
||||||
|
assert.NotEqual(t, settingsCopy.Actions, settings.Actions)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user