root/http/passwd.cc

Revision 92c18c14e163e2ab3200ccad6c6c0e6ee5c3e1a6, 9.8 KB (checked in by Antti-Juhani Kaijanaho <antti-juhani@…>, 21 months ago)

Make Alue self-identity in emails configurable

Fixes #52

Signed-off-by: Antti-Juhani Kaijanaho <antti-juhani@…>

  • Property mode set to 100644
Line 
1/*  This file is part of Alue, the multiprotocol Internet discussion daemon
2
3    Copyright © 2009, 2010 Antti-Juhani Kaijanaho
4
5    Alue is free software: you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    Alue is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with Alue.  If not, see <http://www.gnu.org/licenses/>.
17
18 */
19
20#include "error_resource.hh"
21#include "reauthn_resource.hh"
22#include "redir_resource.hh"
23#include "request.hh"
24#include "templated_resource.hh"
25#include "token.hh"
26
27#include "../config.hh"
28#include "../db/db.hh"
29#include "../db/user.hh"
30#include "../html/util.hh"
31#include "../msg/lexutils.hh"
32#include "../tlate/tlate.hh"
33#include "../smtp_client/smtp_client.hh"
34
35#define REQPATH "/passwd"
36#define REQPREFIX REQPATH "/"
37
38namespace http
39{
40        class passwd : public templated_resource
41        {
42                void chpass(boost::shared_ptr<request>);
43        public:
44                passwd(server::conn_cb cb)
45                        : templated_resource(cb, "passwd.html")
46                        {}
47                void set_attributes(boost::shared_ptr<request>,
48                                    tlate::data_model::ptr);
49        };
50
51        void passwd::chpass(boost::shared_ptr<request> req)
52        {
53                std::string (*const p)(std::string) = uri::percent_encode;
54                std::string (*const dep)(std::string) = uri::percent_decode;
55
56                std::string uid = dep(req->get_form_field("userid"));
57                std::string pw1 = dep(req->get_form_field("password"));
58                std::string pw2 = dep(req->get_form_field("repass"));
59                std::string tokstr = dep(req->get_form_field("token"));
60               
61                boost::shared_ptr<token> &tok = cb.get_http_token(tokstr);
62
63                boost::shared_ptr<db::user> u;
64                if (tokstr.empty())
65                {
66                        if (!req->is_authenticated())
67                        {
68                                boost::shared_ptr<resource> er
69                                        (new reauthn_resource(cb));
70                                throw resource_exception(er);
71                        }
72                        u = req->get_user();
73                        if (u->get_userid() != uid)
74                        {
75                                boost::shared_ptr<resource> er
76                                        (new error_resource
77                                         (cb, "403 User id mismatch"));
78                                throw resource_exception(er);
79                        }
80                }
81                else
82                {
83                         if (tok->kind != token::PASSWD)
84                         {
85                                 boost::shared_ptr<resource> er
86                                         (new error_resource
87                                          (cb, "404 Not found"));
88                                 throw resource_exception(er);
89                         }
90                         
91                         if (tok) u = tok->get_user();
92                         if (!u)
93                         {
94                                 boost::shared_ptr<resource> er
95                                         (new error_resource
96                                          (cb, "403 Opportunity expired"));
97                                 throw resource_exception(er);
98                         }
99                }
100               
101                std::string err = db::user::passwd_problems(pw1);
102
103                if (pw1 != pw2) err = "Passwords did not match.";
104
105                if (!err.empty())
106                {
107                        boost::shared_ptr<resource> rr
108                                (new redir_resource(cb,
109                                                    "/passwd/" +
110                                                    tokstr +
111                                                    "?msg=" +
112                                                    p(err),
113                                                    "303 See other"));
114                        throw resource_exception(rr);
115                }
116
117                u->set_password(pw1);
118
119                if (tok) tok.reset();  // invalidate the link
120
121                std::string ton = u->get_display_name();
122                std::string to = u->get_delivery_email();
123                std::string from =
124                        config["alue-name"].as<std::string>() +
125                        " <" +
126                        config["operator-email"].as<std::string>() +
127                        ">";
128                               
129                tlate::data_model::ptr am(new tlate::data_model);
130
131                am->insert("from", from);
132                am->insert("to", msg::make_phrase(ton) + " <" + to + ">");
133                am->insert("userid",u->get_userid());
134                am->insert("request_ip", req->get_peer().to_string());
135               
136                boost::shared_ptr<tlate::tlate> tl =
137                        tlate::tlate::parse("pwchanged.msg");
138                std::ostringstream mos;
139                mos << tl->eval(am);
140               
141                std::list<std::string> recv;
142                recv.push_back(to);
143               
144                cb.smtpc().send_mail(recv, mos.str());
145
146                boost::shared_ptr<resource> r
147                        (new templated_resource(cb, "passwd-changed.html"));
148                throw resource_exception(r);
149        }
150
151        void passwd::set_attributes(boost::shared_ptr<request> req,
152                                    tlate::data_model::ptr am)
153        {
154                std::string (*const q)(std::string,bool) = html::quote;
155                std::string (*const p)(std::string) = uri::percent_encode;
156                std::string (*const dep)(std::string) = uri::percent_decode;
157
158                if (req->get_path().length() < sizeof REQPREFIX - 1)
159                {
160                        boost::shared_ptr<resource> er
161                                (new error_resource(cb, "404 Not found"));
162                        throw resource_exception(er);
163                }
164
165                boost::shared_ptr<db::user> u;
166                if (req->get_path().length() == sizeof REQPREFIX - 1)
167                {
168                        if (req->get_method() == "POST") return chpass(req);
169                        if (!req->is_authenticated())
170                        {
171                                boost::shared_ptr<resource> er
172                                        (new reauthn_resource(cb));
173                                throw resource_exception(er);
174                        }
175                        u = req->get_user();
176                }
177
178                std::string tokstr;
179                boost::shared_ptr<token> tok;
180                if (!u)
181                {
182                        tokstr = dep
183                                (req->get_path().substr(sizeof REQPREFIX - 1));
184                        tok = cb.get_http_token(tokstr);
185                        if (tok) u = tok->get_user();
186                }
187               
188                if (!u)
189                {
190                        boost::shared_ptr<resource> er
191                                (new error_resource
192                                 (cb, "410 Link expired or otherwise invalid"));
193                        throw resource_exception(er);
194                }
195
196                am->insert("userid", q(u->get_userid(), false));
197                am->insert("username", q(u->get_display_name(), false));
198                if (!tokstr.empty())
199                {
200                        am->insert("token", q(tokstr,false));
201                        am->insert("expiration_time",
202                                   q(to_iso_extended_string
203                                     (tok->expiration_time()),
204                                     false));
205                        using boost::lexical_cast;
206                        using boost::posix_time::second_clock;
207                        boost::posix_time::time_duration ex =
208                                tok->expiration_time() -
209                                second_clock::universal_time();
210                        am->insert("expires_in_hours",
211                                   lexical_cast<std::string>(ex.hours()));
212                        am->insert("expires_in_minutes",
213                                   lexical_cast<std::string>(ex.minutes()));
214                        am->insert("expires_in_seconds",
215                                   lexical_cast<std::string>(ex.seconds()));
216                }
217
218                am->insert("action", p(REQPREFIX));
219                am->insert("method", "post");
220                am->insert("enctype", "application/x-www-form-urlencoded");
221                am->insert("accept_charlist", q("utf8",false));
222
223                std::string errmsg = dep(req->get_form_field("msg"));
224                if (!errmsg.empty())
225                        am->insert("errmsg", q(errmsg, false));
226        }
227
228};
229
230namespace
231{
232        class factory : public server::http_resource_factory
233        {
234        public:
235                factory() {
236                        server::register_http_resource(REQPATH, this);
237                }
238                boost::shared_ptr<http::resource> operator()
239                (server::conn_cb cb, std::string) {
240                        boost::shared_ptr<http::resource> rv
241                                (new http::passwd(cb));
242                        return rv;
243                }
244        };
245        factory f;
246}
Note: See TracBrowser for help on using the browser.