From faf8952b8732d6314e3d3429f5cc761564565e44 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Mon, 14 Feb 2022 21:58:30 +0100 Subject: Send inactivity notification prior to account deletion --- lib/Travelynx/Command/database.pm | 14 ++++++++++++++ lib/Travelynx/Command/maintenance.pm | 32 ++++++++++++++++++++++++++++++-- lib/Travelynx/Helper/Sendmail.pm | 31 +++++++++++++++++++++++++++++++ lib/Travelynx/Model/Users.pm | 21 +++++++++++++++++++-- 4 files changed, 94 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/Travelynx/Command/database.pm b/lib/Travelynx/Command/database.pm index 4f7c792..eb2443c 100644 --- a/lib/Travelynx/Command/database.pm +++ b/lib/Travelynx/Command/database.pm @@ -1,4 +1,5 @@ package Travelynx::Command::database; + # Copyright (C) 2020 Daniel Friesel # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -1055,6 +1056,19 @@ my @migrations = ( } ); }, + + # v23 -> v24 + # travelynx 1.22 warns about upcoming account deletion due to inactivity + sub { + my ($db) = @_; + $db->query( + qq{ + alter table users add column deletion_notified timestamptz; + comment on column users.deletion_notified is 'Time at which warning about upcoming account deletion due to inactivity was sent'; + update schema_version set version = 24; + } + ); + }, ); sub setup_db { diff --git a/lib/Travelynx/Command/maintenance.pm b/lib/Travelynx/Command/maintenance.pm index 5f609cb..58189ff 100644 --- a/lib/Travelynx/Command/maintenance.pm +++ b/lib/Travelynx/Command/maintenance.pm @@ -18,6 +18,7 @@ sub run { my $verification_deadline = $now->clone->subtract( hours => 48 ); my $deletion_deadline = $now->clone->subtract( hours => 72 ); my $old_deadline = $now->clone->subtract( years => 1 ); + my $old_notification_deadline = $now->clone->subtract( weeks => 4 ); my $db = $self->app->pg->db; my $tx = $db->begin; @@ -82,12 +83,39 @@ sub run { printf( "Pruned %d pending mail change(s)\n", $rows ); } + my $to_notify = $db->select( + 'users', + [ 'id', 'name', 'email', 'last_seen' ], + { + last_seen => { '<', $old_deadline }, + deletion_notified => undef + } + ); + + for my $user ( $to_notify->hashes->each ) { + $self->app->sendmail->age_deletion_notification( + name => $user->{name}, + email => $user->{email}, + last_seen => $user->{last_seen}, + login_url => $self->app->base_url_for('login')->to_abs, + account_url => $self->app->base_url_for('account')->to_abs, + imprint_url => $self->app->base_url_for('impressum')->to_abs, + ); + $self->app->users->mark_deletion_notified( uid => $user->{id} ); + } + my $to_delete = $db->select( 'users', ['id'], { deletion_requested => { '<', $deletion_deadline } } ); my @uids_to_delete = $to_delete->arrays->map( sub { shift->[0] } )->each; - $to_delete - = $db->select( 'users', ['id'], { last_seen => { '<', $old_deadline } } ); + $to_delete = $db->select( + 'users', + ['id'], + { + last_seen => { '<', $old_deadline }, + deletion_notified => { '<', $old_notification_deadline } + } + ); push( @uids_to_delete, $to_delete->arrays->map( sub { shift->[0] } )->each ); diff --git a/lib/Travelynx/Helper/Sendmail.pm b/lib/Travelynx/Helper/Sendmail.pm index 8a7b1f1..376861d 100644 --- a/lib/Travelynx/Helper/Sendmail.pm +++ b/lib/Travelynx/Helper/Sendmail.pm @@ -1,4 +1,5 @@ package Travelynx::Helper::Sendmail; + # Copyright (C) 2020 Daniel Friesel # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -41,4 +42,34 @@ sub custom { return try_to_sendmail($reg_mail); } +sub age_deletion_notification { + my ( $self, %opt ) = @_; + my $name = $opt{name}; + my $email = $opt{email}; + my $last_seen = $opt{last_seen}; + my $login_url = $opt{login_url}; + my $account_url = $opt{account_url}; + my $imprint_url = $opt{imprint_url}; + + my $body = "Hallo ${name},\n\n"; + $body + .= "Dein travelynx-Account wurde seit dem ${last_seen} nicht verwendet.\n"; + $body + .= "Im Sinne der Datensparsamkeit wird er daher in vier Wochen gelöscht.\n"; + $body + .= "Falls du den Account weiterverwenden möchtest, kannst du dich unter\n"; + $body .= "<$login_url> anmelden.\n"; + $body + .= "Durch die Anmeldung wird die Löschung automatisch abgebrochen.\n\n"; + $body + .= "Falls du den Account löschen, aber zuvor deine Daten exportieren möchtest,\n"; + $body .= "kannst du dich unter obiger URL anmelden, unter <$account_url>\n"; + $body + .= "deine Daten exportieren und anschließend den Account löschen lassen.\n\n\n"; + $body .= "Impressum: ${imprint_url}\n"; + + return $self->custom( $email, + 'travelynx: Löschung deines Accounts', $body ); +} + 1; diff --git a/lib/Travelynx/Model/Users.pm b/lib/Travelynx/Model/Users.pm index 1371b8a..70d81c4 100644 --- a/lib/Travelynx/Model/Users.pm +++ b/lib/Travelynx/Model/Users.pm @@ -23,8 +23,25 @@ sub mark_seen { $db->update( 'users', - { last_seen => DateTime->now( time_zone => 'Europe/Berlin' ) }, - { id => $uid } + { + last_seen => DateTime->now( time_zone => 'Europe/Berlin' ), + deletion_notified => undef + }, + { id => $uid } + ); +} + +sub mark_deletion_notified { + my ( $self, %opt ) = @_; + my $uid = $opt{uid}; + my $db = $opt{db} // $self->{pg}->db; + + $db->update( + 'users', + { + deletion_notified => DateTime->now( time_zone => 'Europe/Berlin' ), + }, + { id => $uid } ); } -- cgit v1.2.3