Skip to content

Commit 37f97ba

Browse files
committed
internal/users: implement logic to enable/disable user
This also adds tests for the same.
1 parent eb34aed commit 37f97ba

File tree

7 files changed

+239
-0
lines changed

7 files changed

+239
-0
lines changed

internal/users/db/db_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,20 @@ func TestUpdateBrokerForUser(t *testing.T) {
462462
require.Error(t, err, "UpdateBrokerForUser for a nonexistent user should return an error")
463463
}
464464

465+
func TestUpdateDisabledFieldForUser(t *testing.T) {
466+
t.Parallel()
467+
468+
c := initDB(t, "one_user_and_group")
469+
470+
// Update broker for existent user
471+
err := c.UpdateDisabledFieldForUser("user1", true)
472+
require.NoError(t, err, "UpdateDisabledFieldForUser for an existent user should not return an error")
473+
474+
// Error when updating broker for nonexistent user
475+
err = c.UpdateDisabledFieldForUser("nonexistent", false)
476+
require.Error(t, err, "UpdateDisabledFieldForUser for a nonexistent user should return an error")
477+
}
478+
465479
func TestRemoveDb(t *testing.T) {
466480
t.Parallel()
467481

internal/users/db/update.go

+18
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,21 @@ func (m *Manager) UpdateBrokerForUser(username, brokerID string) error {
165165

166166
return nil
167167
}
168+
169+
// UpdateDisabledFieldForUser sets the Disabled field to a given value for a user
170+
func (m *Manager) UpdateDisabledFieldForUser(username string, disabled bool) error {
171+
query := `UPDATE users SET disabled = ? WHERE name = ?`
172+
res, err := m.db.Exec(query, disabled, username)
173+
if err != nil {
174+
return fmt.Errorf("failed to update disabled field for user: %w", err)
175+
}
176+
rowsAffected, err := res.RowsAffected()
177+
if err != nil {
178+
return fmt.Errorf("failed to get rows affected: %w", err)
179+
}
180+
if rowsAffected == 0 {
181+
return NoDataFoundError{table: "users", key: username}
182+
}
183+
184+
return nil
185+
}

internal/users/manager.go

+18
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,24 @@ func (m *Manager) UpdateBrokerForUser(username, brokerID string) error {
334334
return nil
335335
}
336336

337+
// DisableUser sets the Disabled field to true for the given user.
338+
func (m *Manager) DisableUser(username string) error {
339+
if err := m.db.UpdateDisabledFieldForUser(username, true); err != nil {
340+
return err
341+
}
342+
343+
return nil
344+
}
345+
346+
// EnableUser sets the Disabled field to false for the given user.
347+
func (m *Manager) EnableUser(username string) error {
348+
if err := m.db.UpdateDisabledFieldForUser(username, false); err != nil {
349+
return err
350+
}
351+
352+
return nil
353+
}
354+
337355
// IsUserDisabled returns true if the user with the given user name is disabled, false otherwise.
338356
func (m *Manager) IsUserDisabled(username string) (bool, error) {
339357
u, err := m.db.UserByName(username)

internal/users/manager_test.go

+90
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,96 @@ func TestUpdateBrokerForUser(t *testing.T) {
325325
}
326326
}
327327

328+
func TestDisableUser(t *testing.T) {
329+
tests := map[string]struct {
330+
username string
331+
332+
dbFile string
333+
334+
wantErr bool
335+
wantErrType error
336+
}{
337+
"Successfully_update_broker_for_user": {},
338+
339+
"Error_if_user_does_not_exist": {username: "doesnotexist", wantErrType: db.NoDataFoundError{}},
340+
}
341+
for name, tc := range tests {
342+
t.Run(name, func(t *testing.T) {
343+
// We don't care about the output of gpasswd in this test, but we still need to mock it.
344+
_ = localgroupstestutils.SetupGPasswdMock(t, "empty.group")
345+
346+
if tc.username == "" {
347+
tc.username = "user1"
348+
}
349+
if tc.dbFile == "" {
350+
tc.dbFile = "multiple_users_and_groups"
351+
}
352+
353+
dbDir := t.TempDir()
354+
err := db.Z_ForTests_CreateDBFromYAML(filepath.Join("testdata", "db", tc.dbFile+".db.yaml"), dbDir)
355+
require.NoError(t, err, "Setup: could not create database from testdata")
356+
m := newManagerForTests(t, dbDir)
357+
358+
err = m.DisableUser(tc.username)
359+
360+
requireErrorAssertions(t, err, tc.wantErrType, tc.wantErr)
361+
if tc.wantErrType != nil || tc.wantErr {
362+
return
363+
}
364+
365+
got, err := db.Z_ForTests_DumpNormalizedYAML(userstestutils.GetManagerDB(m))
366+
require.NoError(t, err, "Created database should be valid yaml content")
367+
368+
golden.CheckOrUpdate(t, got)
369+
})
370+
}
371+
}
372+
373+
func TestEnableUser(t *testing.T) {
374+
tests := map[string]struct {
375+
username string
376+
377+
dbFile string
378+
379+
wantErr bool
380+
wantErrType error
381+
}{
382+
"Successfully_update_broker_for_user": {},
383+
384+
"Error_if_user_does_not_exist": {username: "doesnotexist", wantErrType: db.NoDataFoundError{}},
385+
}
386+
for name, tc := range tests {
387+
t.Run(name, func(t *testing.T) {
388+
// We don't care about the output of gpasswd in this test, but we still need to mock it.
389+
_ = localgroupstestutils.SetupGPasswdMock(t, "empty.group")
390+
391+
if tc.username == "" {
392+
tc.username = "user1"
393+
}
394+
if tc.dbFile == "" {
395+
tc.dbFile = "disabled_user"
396+
}
397+
398+
dbDir := t.TempDir()
399+
err := db.Z_ForTests_CreateDBFromYAML(filepath.Join("testdata", "db", tc.dbFile+".db.yaml"), dbDir)
400+
require.NoError(t, err, "Setup: could not create database from testdata")
401+
m := newManagerForTests(t, dbDir)
402+
403+
err = m.EnableUser(tc.username)
404+
405+
requireErrorAssertions(t, err, tc.wantErrType, tc.wantErr)
406+
if tc.wantErrType != nil || tc.wantErr {
407+
return
408+
}
409+
410+
got, err := db.Z_ForTests_DumpNormalizedYAML(userstestutils.GetManagerDB(m))
411+
require.NoError(t, err, "Created database should be valid yaml content")
412+
413+
golden.CheckOrUpdate(t, got)
414+
})
415+
}
416+
}
417+
328418
//nolint:dupl // This is not a duplicate test
329419
func TestUserByIDAndName(t *testing.T) {
330420
tests := map[string]struct {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
users:
2+
- name: user1
3+
uid: 1111
4+
gid: 11111
5+
gecos: |-
6+
User1 gecos
7+
On multiple lines
8+
dir: /home/user1
9+
shell: /bin/bash
10+
broker_id: broker-id
11+
disabled: true
12+
groups:
13+
- name: group1
14+
gid: 11111
15+
ugid: "12345678"
16+
users_to_groups:
17+
- uid: 1111
18+
gid: 11111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
users:
2+
- name: user1
3+
uid: 1111
4+
gid: 11111
5+
gecos: |-
6+
User1 gecos
7+
On multiple lines
8+
dir: /home/user1
9+
shell: /bin/bash
10+
broker_id: broker-id
11+
disabled: true
12+
- name: user2
13+
uid: 2222
14+
gid: 22222
15+
gecos: User2
16+
dir: /home/user2
17+
shell: /bin/dash
18+
broker_id: broker-id
19+
- name: user3
20+
uid: 3333
21+
gid: 33333
22+
gecos: User3
23+
dir: /home/user3
24+
shell: /bin/zsh
25+
broker_id: broker-id
26+
- name: userwithoutbroker
27+
uid: 4444
28+
gid: 44444
29+
gecos: userwithoutbroker
30+
dir: /home/userwithoutbroker
31+
shell: /bin/sh
32+
groups:
33+
- name: group1
34+
gid: 11111
35+
ugid: "12345678"
36+
- name: group2
37+
gid: 22222
38+
ugid: "56781234"
39+
- name: group3
40+
gid: 33333
41+
ugid: "34567812"
42+
- name: group4
43+
gid: 44444
44+
ugid: "45678123"
45+
- name: commongroup
46+
gid: 99999
47+
ugid: "87654321"
48+
users_to_groups:
49+
- uid: 1111
50+
gid: 11111
51+
- uid: 1111
52+
gid: 99999
53+
- uid: 2222
54+
gid: 22222
55+
- uid: 2222
56+
gid: 99999
57+
- uid: 3333
58+
gid: 33333
59+
- uid: 3333
60+
gid: 99999
61+
- uid: 4444
62+
gid: 44444
63+
- uid: 4444
64+
gid: 99999
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
users:
2+
- name: user1
3+
uid: 1111
4+
gid: 11111
5+
gecos: |-
6+
User1 gecos
7+
On multiple lines
8+
dir: /home/user1
9+
shell: /bin/bash
10+
broker_id: broker-id
11+
groups:
12+
- name: group1
13+
gid: 11111
14+
ugid: "12345678"
15+
users_to_groups:
16+
- uid: 1111
17+
gid: 11111

0 commit comments

Comments
 (0)