Skip to content

Commit

Permalink
Allow to disable users instead of deleting them.
Browse files Browse the repository at this point in the history
Add new config parameters for disabling normal and guest users and
allow to configure them in the settings UI.

Fixes: #31

Signed-off-by: Jonas <jonas@freesources.org>
  • Loading branch information
mejo- committed Feb 24, 2023
1 parent d7e6160 commit c11eb16
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 4 deletions.
4 changes: 2 additions & 2 deletions js/user_retention-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/user_retention-main.js.map

Large diffs are not rendered by default.

40 changes: 39 additions & 1 deletion lib/Service/RetentionService.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ class RetentionService {
protected IFactory $l10nFactory;
protected LoggerInterface $logger;

protected int $userDaysDisable = 0;
protected int $userDisableMaxLastLogin = 0;
protected int $userDays = 0;
protected int $userMaxLastLogin = 0;
protected int $guestDaysDisable = 0;
protected int $guestDisableMaxLastLogin = 0;
protected int $guestDays = 0;
protected int $guestMaxLastLogin = 0;
protected array $excludedGroups = [];
Expand Down Expand Up @@ -84,6 +88,15 @@ public function __construct(

public function runCron(): void {
$now = new \DateTimeImmutable();
$this->userDaysDisable = (int) $this->config->getAppValue('user_retention', 'user_days_disable', '0');
if ($this->userDaysDisable > 0) {
$userDisableMaxLastLogin = $now->sub(new \DateInterval('P' . $this->userDaysDisable . 'D'));
$this->userDisableMaxLastLogin = $userDisableMaxLastLogin->getTimestamp();
$this->logger->debug('Account disabling with last login before ' . $userDisableMaxLastLogin->format(\DateTimeInterface::ATOM));
} else {
$this->logger->debug('Account disabling is disabled');
}

$this->userDays = (int) $this->config->getAppValue('user_retention', 'user_days', '0');
if ($this->userDays > 0) {
$userMaxLastLogin = $now->sub(new \DateInterval('P' . $this->userDays . 'D'));
Expand All @@ -93,6 +106,15 @@ public function runCron(): void {
$this->logger->debug('Account retention is disabled');
}

$this->guestDaysDisable = (int) $this->config->getAppValue('user_retention', 'guest_days_disable', '0');
if ($this->guestDaysDisable > 0) {
$guestDisableMaxLastLogin = $now->sub(new \DateInterval('P' . $this->guestDaysDisable . 'D'));
$this->guestDisableMaxLastLogin = $guestDisableMaxLastLogin->getTimestamp();
$this->logger->debug('Guest account disabling with last login before ' . $guestDisableMaxLastLogin->format(\DateTimeInterface::ATOM));
} else {
$this->logger->debug('Guest account disabling is disabled');
}

$this->guestDays = (int) $this->config->getAppValue('user_retention', 'guest_days', '0');
if ($this->guestDays > 0) {
$guestMaxLastLogin = $now->sub(new \DateInterval('P' . $this->guestDays . 'D'));
Expand Down Expand Up @@ -130,14 +152,19 @@ public function runCron(): void {
}

public function executeRetentionPolicy(IUser $user): ?bool {
$skipDisableIfNewerThan = $this->userDisableMaxLastLogin;
if ($user->getBackend() instanceof GuestUserBackend) {
$skipDisableIfNewerThan = $this->guestDisableMaxLastLogin;
}

$skipIfNewerThan = $this->userMaxLastLogin;
$policyDays = $this->userDays;
if ($user->getBackend() instanceof GuestUserBackend) {
$skipIfNewerThan = $this->guestMaxLastLogin;
$policyDays = $this->guestDays;
}

if (!$skipIfNewerThan) {
if (!$skipDisableIfNewerThan && !$skipIfNewerThan) {
$this->logger->debug('Skipping retention because not defined for user backend: {user}', [
'user' => $user->getUID(),
]);
Expand All @@ -152,6 +179,17 @@ public function executeRetentionPolicy(IUser $user): ?bool {
return true;
}

// Check if we disable the user
try {
$this->shouldPerformActionOnUser($user, $skipDisableIfNewerThan);

$user->setEnabled(false);
$this->logger->info('Account disabled: ' . $user->getUID());
return true;
} catch (SkipUserException $e) {
// Not disabling yet, continue with checking deletion
}

// Check if we delete the user
try {
$this->shouldPerformActionOnUser($user, $skipIfNewerThan);
Expand Down
4 changes: 4 additions & 0 deletions lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ public function __construct(IConfig $config,
}

public function getForm(): TemplateResponse {
$userDaysDisable = (int) $this->config->getAppValue('user_retention', 'user_days_disable', 0);
$this->initialStateService->provideInitialState('user_days_disable', $userDaysDisable);
$userDays = (int) $this->config->getAppValue('user_retention', 'user_days', 0);
$this->initialStateService->provideInitialState('user_days', $userDays);
$guestDaysDisable = (int) $this->config->getAppValue('user_retention', 'guest_days_disable', 0);
$this->initialStateService->provideInitialState('guest_days_disable', $guestDaysDisable);
$guestDays = (int) $this->config->getAppValue('user_retention', 'guest_days', 0);
$this->initialStateService->provideInitialState('guest_days', $guestDays);

Expand Down
50 changes: 50 additions & 0 deletions src/views/AdminSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@
{{ t('user_retention', 'Accounts from LDAP are deleted locally only, unless the LDAP write support app is enabled. When still available on LDAP, accounts will reappear.') }}
</p>

<div>
<label>
<span>{{ t('user_retention', 'Account disabling:') }}</span>
<input id="user_days_disable"
v-model="userDaysDisable"
type="number"
placeholder="180"
@change="saveUserDaysDisable"> {{ t('user_retention', 'days') }}
<em>{{ t('user_retention', '(0 to disable)') }}</em>
</label>
</div>

<div>
<label>
<span>{{ t('user_retention', 'Account expiration:') }}</span>
Expand All @@ -44,6 +56,18 @@
</label>
</div>

<div v-if="guestsAppInstalled">
<label>
<span>{{ t('user_retention', 'Guest account disabling:') }}</span>
<input id="guest_days_disable"
v-model="guestDaysDisable"
type="number"
placeholder="180"
@change="saveGuestDaysDisable"> {{ t('user_retention', 'days') }}
<em>{{ t('user_retention', '(0 to disable)') }}</em>
</label>
</div>

<div v-if="guestsAppInstalled">
<label>
<span>{{ t('user_retention', 'Guest account expiration:') }}</span>
Expand Down Expand Up @@ -106,15 +130,19 @@ export default {
ldapBackendEnabled: false,
groups: [],
excludedGroups: [],
userDaysDisable: 0,
userDays: 0,
guestDaysDisable: 0,
guestDays: 0,
}
},

mounted() {
this.loading = true

this.userDaysDisable = loadState('user_retention', 'user_days_disable')
this.userDays = loadState('user_retention', 'user_days')
this.guestDaysDisable = loadState('user_retention', 'guest_days_disable')
this.guestDays = loadState('user_retention', 'guest_days')
this.excludedGroups = loadState('user_retention', 'excluded_groups').sort(function(a, b) {
return a.displayname.localeCompare(b.displayname)
Expand Down Expand Up @@ -147,6 +175,17 @@ export default {
}
}, 500),

saveUserDaysDisable() {
OCP.AppConfig.setValue('user_retention', 'user_days_disable', this.userDaysDisable, {
success: () => {
showSuccess(t('user_retention', 'Setting saved'))
},
error: () => {
showError(t('user_retention', 'Could not save the setting'))
},
})
},

saveUserDays() {
OCP.AppConfig.setValue('user_retention', 'user_days', this.userDays, {
success: () => {
Expand All @@ -158,6 +197,17 @@ export default {
})
},

saveGuestDaysDisable() {
OCP.AppConfig.setValue('user_retention', 'guest_days_disable', this.guestDaysDisable, {
success: () => {
showSuccess(t('user_retention', 'Setting saved'))
},
error: () => {
showError(t('user_retention', 'Could not save the setting'))
},
})
},

saveGuestDays() {
OCP.AppConfig.setValue('user_retention', 'guest_days', this.guestDays, {
success: () => {
Expand Down

0 comments on commit c11eb16

Please sign in to comment.