mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 23:00:55 +03:00
EventManager: allow to check for inactive users
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
@@ -607,6 +607,9 @@ func TestEventManagerErrors(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
err = executeUserExpirationCheckRuleAction(dataprovider.ConditionOptions{}, &EventParams{})
|
||||
assert.Error(t, err)
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{},
|
||||
dataprovider.ConditionOptions{}, &EventParams{}, time.Time{})
|
||||
assert.Error(t, err)
|
||||
err = executeDeleteFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, &EventParams{})
|
||||
assert.Error(t, err)
|
||||
err = executeMkdirFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, &EventParams{})
|
||||
@@ -2254,3 +2257,173 @@ func TestMetadataReplacement(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, `{"key":"value"} {\"key\":\"value\"}`, string(data))
|
||||
}
|
||||
|
||||
func TestUserInactivityCheck(t *testing.T) {
|
||||
username1 := "user1"
|
||||
username2 := "user2"
|
||||
user1 := dataprovider.User{
|
||||
BaseUser: sdk.BaseUser{
|
||||
Username: username1,
|
||||
HomeDir: filepath.Join(os.TempDir(), username1),
|
||||
Status: 1,
|
||||
Permissions: map[string][]string{
|
||||
"/": {dataprovider.PermAny},
|
||||
},
|
||||
},
|
||||
}
|
||||
user2 := dataprovider.User{
|
||||
BaseUser: sdk.BaseUser{
|
||||
Username: username2,
|
||||
HomeDir: filepath.Join(os.TempDir(), username2),
|
||||
Status: 1,
|
||||
Permissions: map[string][]string{
|
||||
"/": {dataprovider.PermAny},
|
||||
},
|
||||
},
|
||||
}
|
||||
days := user1.InactivityDays(time.Now().Add(10*24*time.Hour + 5*time.Second))
|
||||
assert.Equal(t, 0, days)
|
||||
|
||||
user2.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
|
||||
err := executeInactivityCheckForUser(&user2, dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
}, time.Now().Add(12*24*time.Hour))
|
||||
assert.Error(t, err)
|
||||
user2.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
|
||||
err = executeInactivityCheckForUser(&user2, dataprovider.EventActionUserInactivity{
|
||||
DeleteThreshold: 10,
|
||||
}, time.Now().Add(12*24*time.Hour))
|
||||
assert.Error(t, err)
|
||||
|
||||
err = dataprovider.AddUser(&user1, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
err = dataprovider.AddUser(&user2, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
user1, err = dataprovider.UserExists(username1, "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, user1.Status)
|
||||
days = user1.InactivityDays(time.Now().Add(10*24*time.Hour + 5*time.Second))
|
||||
assert.Equal(t, 10, days)
|
||||
days = user1.InactivityDays(time.Now().Add(-10*24*time.Hour + 5*time.Second))
|
||||
assert.Equal(t, -9, days)
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: "not matching",
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now().Add(12*24*time.Hour))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user1.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now())
|
||||
assert.NoError(t, err) // no action
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user1.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now().Add(-12*24*time.Hour))
|
||||
assert.NoError(t, err) // no action
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
DeleteThreshold: 20,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user1.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now().Add(30*24*time.Hour))
|
||||
// both thresholds exceeded, the user will be disabled
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "executed inactivity check actions for users")
|
||||
}
|
||||
user1, err = dataprovider.UserExists(username1, "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, user1.Status)
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user1.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now().Add(30*24*time.Hour))
|
||||
assert.NoError(t, err) // already disabled, no action
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
DeleteThreshold: 20,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user1.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now().Add(-30*24*time.Hour))
|
||||
assert.NoError(t, err)
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
DeleteThreshold: 20,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user1.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now())
|
||||
assert.NoError(t, err)
|
||||
user1, err = dataprovider.UserExists(username1, "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, user1.Status)
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DisableThreshold: 10,
|
||||
DeleteThreshold: 20,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user1.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now().Add(30*24*time.Hour)) // the user is disabled, will be now deleted
|
||||
assert.Error(t, err)
|
||||
_, err = dataprovider.UserExists(username1, "")
|
||||
assert.ErrorIs(t, err, util.ErrNotFound)
|
||||
|
||||
err = executeUserInactivityCheckRuleAction(dataprovider.EventActionUserInactivity{
|
||||
DeleteThreshold: 20,
|
||||
}, dataprovider.ConditionOptions{
|
||||
Names: []dataprovider.ConditionPattern{
|
||||
{
|
||||
Pattern: user2.Username,
|
||||
},
|
||||
},
|
||||
}, &EventParams{}, time.Now().Add(30*24*time.Hour)) // no disable threshold, user deleted
|
||||
assert.Error(t, err)
|
||||
_, err = dataprovider.UserExists(username2, "")
|
||||
assert.ErrorIs(t, err, util.ErrNotFound)
|
||||
|
||||
err = dataprovider.DeleteUser(username1, "", "", "")
|
||||
assert.Error(t, err)
|
||||
err = dataprovider.DeleteUser(username2, "", "", "")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user