aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm21
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm1
-rw-r--r--perllib/FixMyStreet/DB/Result/Session.pm21
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm52
-rw-r--r--perllib/FixMyStreet/Script/Inactive.pm174
5 files changed, 248 insertions, 21 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index 8f8d7cc47..7d04f5ff9 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -928,6 +928,12 @@ sub report_edit : Path('report_edit') : Args(1) {
}
$problem->set_inflated_columns(\%columns);
+ if ($c->get_param('closed_updates')) {
+ $problem->set_extra_metadata(closed_updates => 1);
+ } else {
+ $problem->unset_extra_metadata('closed_updates');
+ }
+
$c->forward( '/admin/report_edit_category', [ $problem, $problem->state ne $old_state ] );
$c->forward('update_user', [ $problem ]);
@@ -1911,20 +1917,7 @@ sub user_hide_everywhere : Private {
sub user_remove_account : Private {
my ( $self, $c, $user ) = @_;
$c->forward('user_logout_everywhere', [ $user ]);
- $user->problems->update({ anonymous => 1, name => '', send_questionnaire => 0 });
- $user->comments->update({ anonymous => 1, name => '' });
- $user->alerts->update({ whendisabled => \'current_timestamp' });
- $user->password('', 1);
- $user->update({
- email => 'removed-' . $user->id . '@' . FixMyStreet->config('EMAIL_DOMAIN'),
- email_verified => 0,
- name => '',
- phone => '',
- phone_verified => 0,
- title => undef,
- twitter_id => undef,
- facebook_id => undef,
- });
+ $user->anonymize_account;
$c->stash->{status_message} = _('That user’s personal details have been removed.');
}
diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm
index 13eceadb0..4a5b8db5d 100644
--- a/perllib/FixMyStreet/App/Controller/Report/Update.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm
@@ -240,6 +240,7 @@ This makes sure we only proceed to processing if we've had the form submitted
sub check_form_submitted : Private {
my ( $self, $c ) = @_;
+ return if $c->stash->{problem}->get_extra_metadata('closed_updates');
return $c->get_param('submit_update') || '';
}
diff --git a/perllib/FixMyStreet/DB/Result/Session.pm b/perllib/FixMyStreet/DB/Result/Session.pm
index 4713c99eb..a478c5444 100644
--- a/perllib/FixMyStreet/DB/Result/Session.pm
+++ b/perllib/FixMyStreet/DB/Result/Session.pm
@@ -24,5 +24,24 @@ __PACKAGE__->set_primary_key("id");
# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-08 17:19:55
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:MVmCn4gLQWXTDIIaDHiVmA
-# You can replace this text with custom code or comments, and it will be preserved on regeneration
+use Storable;
+use MIME::Base64;
+
+sub id_code {
+ my $self = shift;
+ my $id = $self->id;
+ $id =~ s/^session://;
+ $id =~ s/\s+$//;
+ return $id;
+}
+
+sub user {
+ my $self = shift;
+ return unless $self->session_data;
+ my $data = Storable::thaw(MIME::Base64::decode($self->session_data));
+ return unless $data->{__user};
+ my $user = $self->result_source->schema->resultset("User")->find($data->{__user}{id});
+ return $user;
+}
+
1;
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index db68236bf..8b539f85d 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -20,10 +20,14 @@ __PACKAGE__->add_columns(
},
"email",
{ data_type => "text", is_nullable => 1 },
+ "email_verified",
+ { data_type => "boolean", default_value => \"false", is_nullable => 0 },
"name",
{ data_type => "text", is_nullable => 1 },
"phone",
{ data_type => "text", is_nullable => 1 },
+ "phone_verified",
+ { data_type => "boolean", default_value => \"false", is_nullable => 0 },
"password",
{ data_type => "text", default_value => "", is_nullable => 0 },
"from_body",
@@ -42,10 +46,20 @@ __PACKAGE__->add_columns(
{ data_type => "integer", is_nullable => 1 },
"extra",
{ data_type => "text", is_nullable => 1 },
- "email_verified",
- { data_type => "boolean", default_value => \"false", is_nullable => 0 },
- "phone_verified",
- { data_type => "boolean", default_value => \"false", is_nullable => 0 },
+ "created",
+ {
+ data_type => "timestamp",
+ default_value => \"current_timestamp",
+ is_nullable => 0,
+ original => { default_value => \"now()" },
+ },
+ "last_active",
+ {
+ data_type => "timestamp",
+ default_value => \"current_timestamp",
+ is_nullable => 0,
+ original => { default_value => \"now()" },
+ },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("users_facebook_id_key", ["facebook_id"]);
@@ -105,8 +119,8 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-09-19 18:02:17
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:OKHKCSahWD3Ov6ulj+2f/w
+# Created by DBIx::Class::Schema::Loader v0.07035 @ 2018-05-23 18:54:36
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/V7+Ygv/t6VX8dDhNGN16w
# These are not fully unique constraints (they only are when the *_verified
# is true), but this is managed in ResultSet::User's find() wrapper.
@@ -442,6 +456,25 @@ sub adopt {
$other->delete;
}
+sub anonymize_account {
+ my $self = shift;
+
+ $self->problems->update({ anonymous => 1, name => '', send_questionnaire => 0 });
+ $self->comments->update({ anonymous => 1, name => '' });
+ $self->alerts->update({ whendisabled => \'current_timestamp' });
+ $self->password('', 1);
+ $self->update({
+ email => 'removed-' . $self->id . '@' . FixMyStreet->config('EMAIL_DOMAIN'),
+ email_verified => 0,
+ name => '',
+ phone => '',
+ phone_verified => 0,
+ title => undef,
+ twitter_id => undef,
+ facebook_id => undef,
+ });
+}
+
# Planned reports / shortlist
# Override the default auto-created function as we only want one live entry so
@@ -511,4 +544,11 @@ has categories => (
},
);
+sub set_last_active {
+ my $self = shift;
+ my $time = shift;
+ $self->unset_extra_metadata('inactive_email_sent');
+ $self->last_active($time or \'current_timestamp');
+}
+
1;
diff --git a/perllib/FixMyStreet/Script/Inactive.pm b/perllib/FixMyStreet/Script/Inactive.pm
new file mode 100644
index 000000000..0468d2a52
--- /dev/null
+++ b/perllib/FixMyStreet/Script/Inactive.pm
@@ -0,0 +1,174 @@
+package FixMyStreet::Script::Inactive;
+
+use v5.14;
+use warnings;
+
+use Moo;
+use CronFns;
+use FixMyStreet;
+use FixMyStreet::Cobrand;
+use FixMyStreet::DB;
+use FixMyStreet::Email;
+
+has anonymize => ( is => 'ro' );
+has close => ( is => 'ro' );
+has email => ( is => 'ro' );
+has verbose => ( is => 'ro' );
+has dry_run => ( is => 'ro' );
+
+sub BUILDARGS {
+ my ($cls, %args) = @_;
+ $args{dry_run} = delete $args{'dry-run'};
+ return \%args;
+}
+
+has cobrand => (
+ is => 'lazy',
+ default => sub {
+ my $base_url = FixMyStreet->config('BASE_URL');
+ my $site = CronFns::site($base_url);
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($site)->new;
+ $cobrand->set_lang_and_domain(undef, 1);
+ $cobrand;
+ },
+);
+
+has anonymous_user => (
+ is => 'lazy',
+ default => sub {
+ FixMyStreet::DB->resultset("User")->find_or_create({
+ email => 'removed-automatically@' . FixMyStreet->config('EMAIL_DOMAIN'),
+ });
+ }
+);
+
+sub users {
+ my $self = shift;
+
+ say "DRY RUN" if $self->dry_run;
+ $self->anonymize_users;
+ $self->email_inactive_users if $self->email;
+}
+
+sub reports {
+ my $self = shift;
+
+ say "DRY RUN" if $self->dry_run;
+ $self->anonymize_reports if $self->anonymize;
+ $self->close_updates if $self->close;
+}
+
+sub close_updates {
+ my $self = shift;
+
+ my $problems = FixMyStreet::DB->resultset("Problem")->search({
+ lastupdate => { '<', interval($self->close) },
+ state => [ FixMyStreet::DB::Result::Problem->closed_states(), FixMyStreet::DB::Result::Problem->fixed_states() ],
+ extra => [ undef, { -not_like => '%closed_updates%' } ],
+ });
+
+ while (my $problem = $problems->next) {
+ say "Closing updates on problem #" . $problem->id if $self->verbose;
+ next if $self->dry_run;
+ $problem->set_extra_metadata( closed_updates => 1 );
+ $problem->update;
+ }
+}
+
+sub anonymize_reports {
+ my $self = shift;
+
+ # Need to look though them all each time, in case any new updates/alerts
+ my $problems = FixMyStreet::DB->resultset("Problem")->search({
+ lastupdate => { '<', interval($self->anonymize) },
+ state => [
+ FixMyStreet::DB::Result::Problem->closed_states(),
+ FixMyStreet::DB::Result::Problem->fixed_states(),
+ FixMyStreet::DB::Result::Problem->hidden_states(),
+ ],
+ });
+
+ while (my $problem = $problems->next) {
+ say "Anonymizing problem #" . $problem->id if $self->verbose;
+ next if $self->dry_run;
+
+ # Remove personal data from the report
+ $problem->update({
+ user => $self->anonymous_user,
+ name => '',
+ anonymous => 1,
+ send_questionnaire => 0,
+ }) if $problem->user != $self->anonymous_user;
+
+ # Remove personal data from the report's updates
+ $problem->comments->search({
+ user_id => { '!=' => $self->anonymous_user->id },
+ })->update({
+ user_id => $self->anonymous_user->id,
+ name => '',
+ anonymous => 1,
+ });
+
+ # Remove alerts - could just delete, but of interest how many there were, perhaps?
+ FixMyStreet::DB->resultset('Alert')->search({
+ user_id => { '!=' => $self->anonymous_user->id },
+ alert_type => 'new_updates',
+ parameter => $problem->id,
+ })->update({
+ user_id => $self->anonymous_user->id,
+ whendisabled => \'current_timestamp',
+ });
+ }
+}
+
+sub anonymize_users {
+ my $self = shift;
+
+ my $users = FixMyStreet::DB->resultset("User")->search({
+ last_active => { '<', interval($self->anonymize) },
+ });
+
+ while (my $user = $users->next) {
+ say "Anonymizing user #" . $user->id if $self->verbose;
+ next if $self->dry_run;
+ $user->anonymize_account;
+ }
+}
+
+sub email_inactive_users {
+ my $self = shift;
+
+ my $users = FixMyStreet::DB->resultset("User")->search({
+ last_active => [ -and => { '<', interval($self->email) },
+ { '>=', interval($self->anonymize) } ],
+ });
+ while (my $user = $users->next) {
+ next if $user->get_extra_metadata('inactive_email_sent');
+
+ say "Emailing user #" . $user->id if $self->verbose;
+ next if $self->dry_run;
+ FixMyStreet::Email::send_cron(
+ $user->result_source->schema,
+ 'inactive-account.txt',
+ {
+ email_from => $self->email,
+ anonymize_from => $self->anonymize,
+ user => $user,
+ url => $self->cobrand->base_url_with_lang . '/my',
+ },
+ { To => [ $user->email, $user->name ] },
+ undef, 0, $self->cobrand,
+ );
+
+ $user->set_extra_metadata('inactive_email_sent', 1);
+ $user->update;
+ }
+}
+
+sub interval {
+ my $interval = shift;
+ my $s = "current_timestamp - '$interval months'::interval";
+ return \$s;
+}
+
+1;