]> ruin.nu Git - ndwebbie.git/blob - lib/NDWeb/Controller/Settings.pm
Be more paranoid with param in list context
[ndwebbie.git] / lib / NDWeb / Controller / Settings.pm
1 package NDWeb::Controller::Settings;
2
3 use strict;
4 use warnings;
5 use feature ":5.10";
6 use parent 'Catalyst::Controller';
7
8 use NDWeb::Include;
9
10 use DateTime::TimeZone;
11 use Mail::Sendmail;
12 use Email::Valid;
13
14 =head1 NAME
15
16 NDWeb::Controller::Settings - Catalyst Controller
17
18 =head1 DESCRIPTION
19
20 Catalyst Controller.
21
22 =head1 METHODS
23
24 =cut
25
26
27 =head2 index 
28
29 =cut
30
31 sub index :Path :Args(0) {
32         my ( $self, $c ) = @_;
33         my $dbh = $c->model;
34
35         $c->stash(error => $c->flash->{error});
36
37         my @stylesheets = ('Default');
38         my $dir = $c->path_to('root/static/css/black.css')->dir;
39         while (my $file = $dir->next){
40                 if(!$file->is_dir && $file->basename =~ m{^(\w+)\.css$}){
41                         push @stylesheets,$1;
42                 }
43         }
44         $c->stash(stylesheets => \@stylesheets);
45
46         my ($birthday,$timezone,$email,$discord_id) = $dbh->selectrow_array(q{
47 SELECT birthday,timezone,email,discord_id FROM users WHERE uid = $1
48                 },undef,$c->user->id);
49         $c->stash(birthday => $birthday);
50         $c->stash(email =>  $c->flash->{email} // $email);
51         $c->stash(discord_id =>  $c->flash->{discord_id} // $discord_id);
52
53         my @timezone = split m{/},$timezone,2;
54         $c->stash(timezone => \@timezone);
55
56         my @cat = DateTime::TimeZone->categories;
57         unshift @cat, 'GMT';
58         $c->stash(tzcategories => \@cat);
59
60         my @countries = DateTime::TimeZone->names_in_category($timezone[0]);
61         $c->stash(tzcountries => \@countries);
62 }
63
64 sub changeStylesheet : Local {
65         my ( $self, $c ) = @_;
66         my $dbh = $c->model;
67
68         my $query = $dbh->prepare(q{UPDATE users SET css = NULLIF($2,'Default')
69                 WHERE uid = $1
70         });
71         my $css = html_escape $c->req->param('stylesheet');
72         $query->execute($c->user->id,$css);
73
74         $c->res->redirect($c->uri_for(''));
75 }
76
77 sub changeBirthday : Local {
78         my ( $self, $c ) = @_;
79         my $dbh = $c->model;
80
81         my $query = $dbh->prepare(q{UPDATE users SET birthday = NULLIF($2,'')::date
82                 WHERE uid = $1
83                 });
84         eval{
85                 my $birthday = html_escape $c->req->param('birthday');
86                 $query->execute($c->user->id,$birthday);
87         };
88         if ($@){
89                 if ($@ =~ /invalid input syntax for type date/){
90                         $c->flash(error => 'Bad syntax for day, use YYYY-MM-DD.');
91                 }else{
92                         $c->flash(error => $@);
93                 }
94         }
95         $c->res->redirect($c->uri_for(''));
96 }
97
98 sub changeTimezone : Local {
99         my ( $self, $c ) = @_;
100         my $dbh = $c->model;
101
102         my $timezone = $c->req->param('timezone');
103         my $query = $dbh->prepare(q{UPDATE users SET timezone = $2 WHERE uid = $1});
104         eval{
105                 $dbh->selectrow_array(q{SELECT NOW() AT TIME ZONE $1},undef,$timezone);
106                 $query->execute($c->user->id,$timezone );
107         };
108         if ($@){
109                 $c->flash(error => $@);
110         }
111         $c->res->redirect($c->uri_for(''));
112 }
113
114 sub changePassword : Local {
115         my ( $self, $c ) = @_;
116         my $dbh = $c->model;
117
118         my $pass = $c->req->param('pass');
119         if (length $pass < 4) {
120                 $c->flash(error => "Your password need to be at least 4 characters");
121         } else {
122                 my $query = $dbh->prepare(q{UPDATE users SET password = $1
123                         WHERE password = crypt($2,password) AND uid = $3
124                 });
125                 my $oldpass = $c->req->param('oldpass');
126                 $query->execute($pass,$oldpass,$c->user->id);
127
128                 $c->flash(error => "Old password was invalid") unless $query->rows;
129         }
130
131         $c->res->redirect($c->uri_for(''));
132 }
133
134 sub changeEmail : Local {
135         my ( $self, $c ) = @_;
136         my $dbh = $c->model;
137
138         my $email = $c->req->param('email');
139
140         if ($email =~ /^\s*$/) {
141                 my $update = $dbh->prepare(q{
142 UPDATE users SET email = NULL WHERE uid = $1;
143                         });
144                 $update->execute($c->user->id);
145                 $c->flash(error => 'email cleared');
146                 $c->res->redirect($c->uri_for(''));
147                 return,
148         }
149
150         unless (Email::Valid->address($email)){
151                 $c->flash(email => $email);
152                 $c->flash(error => 'Invalid email address');
153                 $c->res->redirect($c->uri_for(''));
154                 return,
155         }
156
157         eval{
158                 my $insert = $dbh->prepare(q{
159 INSERT INTO email_change (uid,email) VALUES ($1,$2) RETURNING id;
160                         });
161                 $insert->execute($c->user->id,$email);
162
163                 my ($id) = $insert->fetchrow_array;
164
165                 my %mail = (
166                         smtp => 'localhost',
167                         To      => $email,
168                         From    => 'NewDawn Command <nd@ruin.nu>',
169                         'Content-type' => 'text/plain; charset="UTF-8"',
170                         Subject => 'Change email address',
171                         Message => qq{
172 You have requested to change email address on the NewDawn website.
173 If that is not the case, then feel free to ignore this email. Otherwise
174 use the following url to confirm the change:
175
176 }.$c->uri_for('confirmEmail',$id)."\n",
177                 );
178
179                 if (sendmail %mail) {
180                         $c->flash(error => 'Sent mail for confirmation.');
181                 }else {
182                         $c->flash(error => $Mail::Sendmail::error);
183                 }
184         };
185         if($@){
186                 if($@ =~ /duplicate key value violates unique constraint/){
187                         $c->flash(email => $email);
188                         $c->flash(error => 'Something went wrong, try to set the email again');
189                 }else{
190                         die $@;
191                 }
192         }
193         $c->res->redirect($c->uri_for(''));
194 }
195
196 sub changeDiscordId : Local {
197         my ( $self, $c ) = @_;
198         my $dbh = $c->model;
199
200         my $discord_id = $c->req->param('discord_id');
201
202         if ($discord_id =~ /^\s*$/) {
203                 my $update = $dbh->prepare(q{
204 UPDATE users SET discord_id = NULL WHERE uid = $1;
205                         });
206                 $update->execute($c->user->id);
207                 $c->flash(error => 'discord id cleared');
208                 $c->res->redirect($c->uri_for(''));
209                 return,
210         }
211
212         eval{
213                 my $update = $dbh->prepare(q{
214 UPDATE users SET discord_id = $2 WHERE uid = $1;
215                         });
216                 $update->execute($c->user->id,$discord_id);
217         };
218         if($@){
219                 if($@ =~ /duplicate key value violates unique constraint/){
220                         $c->flash(discord_id => $discord_id);
221                         $c->flash(error => 'Someone else is using this discord id, duplicate account?');
222                 }else{
223                         die $@;
224                 }
225         }
226         $c->res->redirect($c->uri_for(''));
227 }
228
229 sub confirmEmail : Local {
230         my ( $self, $c, $id ) = @_;
231         my $dbh = $c->model;
232
233         $dbh->begin_work;
234         my $query = $dbh->prepare(q{
235 UPDATE email_change SET confirmed = TRUE
236 WHERE uid = $1 AND id = $2 AND NOT confirmed
237 RETURNING email
238                 });
239         $query->execute($c->user->id,$id);
240         my ($email) = $query->fetchrow_array;
241
242         if ($email){
243                 $dbh->do(q{UPDATE users SET email = $2 WHERE uid = $1}
244                         ,undef,$c->user->id,$email);
245                 $c->flash(error => "Email updated.");
246         }else{
247                 $c->flash(error => "$id is not a valid change id for your account, or already confirmed");
248         }
249         $dbh->commit;
250         $c->res->redirect($c->uri_for(''));
251 }
252
253
254 =head1 AUTHOR
255
256 Michael Andreen (harv@ruin.nu)
257
258 =head1 LICENSE
259
260 GPL 2.0, or later.
261
262 =cut
263
264 1;