Skip to content

Commit 60ec466

Browse files
enhance: serialize user update methods
1 parent f77d8a0 commit 60ec466

15 files changed

Lines changed: 393 additions & 235 deletions

File tree

‎api/oidc.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ func (a *OIDCAPI) registerUser(username, oidcID string, hasAdminGroup bool) (*mo
519519
return nil, http.StatusInternalServerError, fmt.Errorf("failed to create user: %w", err)
520520
}
521521
log.Info().Str("oidc_id", oidcID).Str("username", user.Name).Bool("admin", user.Admin).Msg("OIDC auto registration")
522-
if err := a.UserChangeNotifier.fireUserAdded(user.ID); err != nil {
522+
if err := a.UserChangeNotifier.fireUserAdded(a.DB, user.ID); err != nil {
523523
log.Error().Err(err).Uint("user_id", user.ID).Msg("Could not notify user change")
524524
}
525525
return user, 0, nil

‎api/oidc_test.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"github.com/gin-gonic/gin"
1515
"github.com/gotify/server/v3/auth"
16+
"github.com/gotify/server/v3/database"
1617
"github.com/gotify/server/v3/decaymap"
1718
"github.com/gotify/server/v3/mode"
1819
"github.com/gotify/server/v3/model"
@@ -49,7 +50,7 @@ func (s *OIDCSuite) BeforeTest(suiteName, testName string) {
4950
s.db = testdb.NewDB(s.T())
5051
s.notified = false
5152
notifier := new(UserChangeNotifier)
52-
notifier.OnUserAdded(func(uint) error {
53+
notifier.OnUserAdded(func(tx *database.GormDatabase, uid uint) error {
5354
s.notified = true
5455
return nil
5556
})

‎api/plugin.go‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (c *PluginAPI) GetPlugins(ctx *gin.Context) {
8080
Website: info.Website,
8181
License: info.License,
8282
Enabled: conf.Enabled,
83-
Capabilities: inst.Supports().Strings(),
83+
Capabilities: inst.Instance().Supports().Strings(),
8484
})
8585
}
8686
}
@@ -255,7 +255,7 @@ func (c *PluginAPI) GetDisplay(ctx *gin.Context) {
255255
ctx.AbortWithError(404, errors.New("plugin instance not found"))
256256
return
257257
}
258-
ctx.JSON(200, instance.GetDisplay(location.Get(ctx)))
258+
ctx.JSON(200, instance.Instance().GetDisplay(location.Get(ctx)))
259259
})
260260
}
261261

@@ -317,7 +317,7 @@ func (c *PluginAPI) GetConfig(ctx *gin.Context) {
317317
return
318318
}
319319

320-
if aborted := supportOrAbort(ctx, instance, compat.Configurer); aborted {
320+
if aborted := supportOrAbort(ctx, instance.Instance(), compat.Configurer); aborted {
321321
return
322322
}
323323

@@ -381,11 +381,11 @@ func (c *PluginAPI) UpdateConfig(ctx *gin.Context) {
381381
return
382382
}
383383

384-
if aborted := supportOrAbort(ctx, instance, compat.Configurer); aborted {
384+
if aborted := supportOrAbort(ctx, instance.Instance(), compat.Configurer); aborted {
385385
return
386386
}
387387

388-
newConf := instance.DefaultConfig()
388+
newConf := instance.Instance().DefaultConfig()
389389
newconfBytes, err := io.ReadAll(ctx.Request.Body)
390390
if err != nil {
391391
ctx.AbortWithError(500, err)
@@ -395,7 +395,7 @@ func (c *PluginAPI) UpdateConfig(ctx *gin.Context) {
395395
ctx.AbortWithError(400, err)
396396
return
397397
}
398-
if err := instance.ValidateAndSetConfig(newConf); err != nil {
398+
if err := instance.Instance().ValidateAndSetConfig(newConf); err != nil {
399399
ctx.AbortWithError(400, err)
400400
return
401401
}

‎api/plugin_test.go‎

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"net/http/httptest"
9+
"sync"
910
"testing"
1011

1112
"github.com/gin-gonic/gin"
@@ -29,6 +30,7 @@ type PluginSuite struct {
2930
suite.Suite
3031
db *testdb.Database
3132
a *PluginAPI
33+
u *UserAPI
3234
ctx *gin.Context
3335
recorder *httptest.ResponseRecorder
3436
manager *plugin.Manager
@@ -39,19 +41,23 @@ func (s *PluginSuite) BeforeTest(suiteName, testName string) {
3941
mode.Set(mode.TestDev)
4042
s.db = testdb.NewDB(s.T())
4143
s.resetRecorder()
42-
manager, err := plugin.NewManager(s.db, "", nil, s)
44+
manager, err := plugin.NewManager(s.db.GormDatabase, "", nil, s)
4345
assert.Nil(s.T(), err)
4446
s.manager = manager
4547
withURL(s.ctx, "http", "example.com")
4648
s.a = &PluginAPI{DB: s.db, Manager: manager, Notifier: s}
49+
s.u = &UserAPI{DB: s.db.GormDatabase, UserChangeNotifier: &UserChangeNotifier{}}
4750

4851
mockPluginCompat := new(mock.Plugin)
4952
assert.Nil(s.T(), s.manager.LoadPlugin(mockPluginCompat))
5053

51-
s.db.User(1)
52-
assert.Nil(s.T(), s.manager.InitializeForUserID(1))
53-
s.db.User(2)
54-
assert.Nil(s.T(), s.manager.InitializeForUserID(2))
54+
s.db.NewUserWithNameAdmin(1, "user1", true)
55+
wg := &sync.WaitGroup{}
56+
assert.Nil(s.T(), s.manager.InitializeForUserID(s.db.GormDatabase, 1, wg))
57+
wg.Wait()
58+
s.db.NewUserWithNameAdmin(2, "user2", true)
59+
assert.Nil(s.T(), s.manager.InitializeForUserID(s.db.GormDatabase, 2, wg))
60+
wg.Wait()
5561

5662
s.db.CreatePluginConf(&model.PluginConf{
5763
UserID: 1,
@@ -97,6 +103,31 @@ func (s *PluginSuite) Test_GetPlugins() {
97103
assert.False(s.T(), pluginConfs[0].Enabled, "Plugins should be disabled by default")
98104
}
99105

106+
func (s *PluginSuite) Test_DeleteUser() {
107+
test.WithUser(s.ctx, 1)
108+
109+
s.ctx.Request = httptest.NewRequest("POST", "/plugin/1/enable", nil)
110+
s.ctx.Params = gin.Params{{Key: "id", Value: "1"}}
111+
s.a.EnablePlugin(s.ctx)
112+
113+
assert.Equal(s.T(), 200, s.recorder.Code)
114+
115+
if pluginConf, err := s.db.GetPluginConfByUserAndPath(1, mock.ModulePath); assert.NoError(s.T(), err) {
116+
assert.True(s.T(), pluginConf.Enabled)
117+
}
118+
s.resetRecorder()
119+
120+
s.ctx.Request = httptest.NewRequest("DELETE", "/user/1", nil)
121+
s.ctx.Params = gin.Params{{Key: "id", Value: "1"}}
122+
s.u.DeleteUserByID(s.ctx)
123+
124+
assert.Equal(s.T(), 200, s.recorder.Code)
125+
126+
user, err := s.db.GetUserByID(1)
127+
assert.NoError(s.T(), err)
128+
assert.Nil(s.T(), user)
129+
}
130+
100131
func (s *PluginSuite) Test_EnableDisablePlugin() {
101132
{
102133
test.WithUser(s.ctx, 1)
@@ -161,7 +192,9 @@ func (s *PluginSuite) Test_EnableDisablePlugin() {
161192

162193
func (s *PluginSuite) Test_EnableDisablePlugin_EnableReturnsError_expect500() {
163194
s.db.User(16)
164-
assert.Nil(s.T(), s.manager.InitializeForUserID(16))
195+
wg := &sync.WaitGroup{}
196+
assert.Nil(s.T(), s.manager.InitializeForUserID(s.db.GormDatabase, 16, wg))
197+
wg.Wait()
165198
mock.ReturnErrorOnEnableForUser(16, errors.New("test error"))
166199
conf, err := s.db.GetPluginConfByUserAndPath(16, mock.ModulePath)
167200
assert.NoError(s.T(), err)
@@ -183,7 +216,9 @@ func (s *PluginSuite) Test_EnableDisablePlugin_EnableReturnsError_expect500() {
183216

184217
func (s *PluginSuite) Test_EnableDisablePlugin_DisableReturnsError_expect500() {
185218
s.db.User(17)
186-
assert.Nil(s.T(), s.manager.InitializeForUserID(17))
219+
wg := &sync.WaitGroup{}
220+
assert.Nil(s.T(), s.manager.InitializeForUserID(s.db.GormDatabase, 17, wg))
221+
wg.Wait()
187222
mock.ReturnErrorOnDisableForUser(17, errors.New("test error"))
188223
conf, err := s.db.GetPluginConfByUserAndPath(17, mock.ModulePath)
189224
assert.NoError(s.T(), err)
@@ -291,7 +326,7 @@ func (s *PluginSuite) Test_GetDisplay() {
291326
assert.NoError(s.T(), err)
292327
inst, err := s.manager.Instance(conf.ID)
293328
assert.Nil(s.T(), err)
294-
mockInst := inst.(*mock.PluginInstance)
329+
mockInst := inst.Instance().(*mock.PluginInstance)
295330

296331
mockInst.DisplayString = "test string"
297332

@@ -312,7 +347,7 @@ func (s *PluginSuite) Test_GetDisplay_NotImplemented_expectEmptyString() {
312347
assert.NoError(s.T(), err)
313348
inst, err := s.manager.Instance(conf.ID)
314349
assert.Nil(s.T(), err)
315-
mockInst := inst.(*mock.PluginInstance)
350+
mockInst := inst.Instance().(*mock.PluginInstance)
316351

317352
mockInst.SetCapability(compat.Displayer, false)
318353
defer mockInst.SetCapability(compat.Displayer, true)
@@ -334,7 +369,7 @@ func (s *PluginSuite) Test_GetDisplay_incorrectUser_expectNotFound() {
334369
assert.NoError(s.T(), err)
335370
inst, err := s.manager.Instance(conf.ID)
336371
assert.Nil(s.T(), err)
337-
mockInst := inst.(*mock.PluginInstance)
372+
mockInst := inst.Instance().(*mock.PluginInstance)
338373

339374
mockInst.DisplayString = "test string"
340375

@@ -380,7 +415,7 @@ func (s *PluginSuite) Test_GetConfig() {
380415
assert.NoError(s.T(), err)
381416
inst, err := s.manager.Instance(conf.ID)
382417
assert.Nil(s.T(), err)
383-
mockInst := inst.(*mock.PluginInstance)
418+
mockInst := inst.Instance().(*mock.PluginInstance)
384419

385420
assert.Equal(s.T(), mockInst.DefaultConfig(), mockInst.Config, "Initial config should be default config")
386421
{
@@ -402,7 +437,7 @@ func (s *PluginSuite) Test_GetConfg_notImplemeted_expect400() {
402437
assert.NoError(s.T(), err)
403438
inst, err := s.manager.Instance(conf.ID)
404439
assert.Nil(s.T(), err)
405-
mockInst := inst.(*mock.PluginInstance)
440+
mockInst := inst.Instance().(*mock.PluginInstance)
406441

407442
mockInst.SetCapability(compat.Configurer, false)
408443
defer mockInst.SetCapability(compat.Configurer, true)
@@ -464,7 +499,7 @@ func (s *PluginSuite) Test_UpdateConfig() {
464499
assert.NoError(s.T(), err)
465500
inst, err := s.manager.Instance(conf.ID)
466501
assert.Nil(s.T(), err)
467-
mockInst := inst.(*mock.PluginInstance)
502+
mockInst := inst.Instance().(*mock.PluginInstance)
468503

469504
newConfig := &mock.PluginConfig{
470505
TestKey: "test__new__config",
@@ -499,7 +534,7 @@ func (s *PluginSuite) Test_UpdateConfig_invalidConfig_expect400() {
499534
assert.NoError(s.T(), err)
500535
inst, err := s.manager.Instance(conf.ID)
501536
assert.Nil(s.T(), err)
502-
mockInst := inst.(*mock.PluginInstance)
537+
mockInst := inst.Instance().(*mock.PluginInstance)
503538
origConfig := mockInst.Config
504539

505540
newConfig := &mock.PluginConfig{
@@ -536,7 +571,7 @@ func (s *PluginSuite) Test_UpdateConfig_malformedYAML_expect400() {
536571
assert.NoError(s.T(), err)
537572
inst, err := s.manager.Instance(conf.ID)
538573
assert.Nil(s.T(), err)
539-
mockInst := inst.(*mock.PluginInstance)
574+
mockInst := inst.Instance().(*mock.PluginInstance)
540575
origConfig := mockInst.Config
541576

542577
newConfigYAML := []byte(`--- "rg e""`)
@@ -568,7 +603,7 @@ func (s *PluginSuite) Test_UpdateConfig_ioError_expect500() {
568603
assert.NoError(s.T(), err)
569604
inst, err := s.manager.Instance(conf.ID)
570605
assert.Nil(s.T(), err)
571-
mockInst := inst.(*mock.PluginInstance)
606+
mockInst := inst.Instance().(*mock.PluginInstance)
572607
origConfig := mockInst.Config
573608

574609
{
@@ -598,7 +633,7 @@ func (s *PluginSuite) Test_UpdateConfig_notImplemented_expect400() {
598633
assert.NoError(s.T(), err)
599634
inst, err := s.manager.Instance(conf.ID)
600635
assert.Nil(s.T(), err)
601-
mockInst := inst.(*mock.PluginInstance)
636+
mockInst := inst.Instance().(*mock.PluginInstance)
602637

603638
newConfig := &mock.PluginConfig{
604639
TestKey: "test__new__config",
@@ -626,7 +661,7 @@ func (s *PluginSuite) Test_UpdateConfig_incorrectUser_expectNotFound() {
626661
assert.NoError(s.T(), err)
627662
inst, err := s.manager.Instance(conf.ID)
628663
assert.Nil(s.T(), err)
629-
mockInst := inst.(*mock.PluginInstance)
664+
mockInst := inst.Instance().(*mock.PluginInstance)
630665
origConfig := mockInst.Config
631666

632667
newConfig := &mock.PluginConfig{

‎api/stream/stream.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/gorilla/websocket"
1313
"github.com/gotify/server/v3/auth"
1414
"github.com/gotify/server/v3/config"
15+
"github.com/gotify/server/v3/database"
1516
"github.com/gotify/server/v3/model"
1617
)
1718

@@ -51,7 +52,7 @@ func (a *API) CollectConnectedClientTokens() []string {
5152
}
5253

5354
// NotifyDeletedUser closes existing connections for the given user.
54-
func (a *API) NotifyDeletedUser(userID uint) error {
55+
func (a *API) NotifyDeletedUser(tx *database.GormDatabase, userID uint) error {
5556
a.lock.Lock()
5657
defer a.lock.Unlock()
5758
if clients, ok := a.clients[userID]; ok {

‎api/stream/stream_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ func TestDeleteUser(t *testing.T) {
322322
expectNoMessage(userTwo...)
323323
expectNoMessage(userThree...)
324324

325-
api.NotifyDeletedUser(1)
325+
api.NotifyDeletedUser(nil, 1)
326326

327327
api.Notify(1, &model.MessageExternal{ID: 2, Message: "there"})
328328
expectNoMessage(userOne...)

0 commit comments

Comments
 (0)