root/db/user.cc

Revision f2c6ab73bbeb02eb513a3952a380305eeeae60ff, 10.3 KB (checked in by ajk <ajk@…>, 16 months ago)

#82: Integrate sub/unsub messages and email confirmation messages

Signed-off-by: ajk <ajk@…>

  • Property mode set to 100644
Line 
1/*  This file is part of Alue, the multiprotocol Internet discussion daemon
2
3    Copyright © 2009, 2010, 2011 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 "db.hh"
21#include "user.hh"
22#include "role.hh"
23
24#include "../config.hh"
25#include "../msg/lexutils.hh"
26#include "../smtp_client/smtp_client.hh"
27#include "../tlate/data_model.hh"
28#include "../tlate/tlate.hh"
29#include "../tlate/user_value.hh"
30#include "../uri.hh"
31
32#include <sstream>
33
34namespace
35{
36        std::string mktoken()
37        {
38                std::string token;
39                boost::random_device rand;
40                for (size_t i = 0; i < 30; i++)
41                        token += util::b64_char(rand() % 64);
42                token += "99"; /* just in case the last char
43                                  is punctuation, in order to
44                                  not confuse users */
45                return token;
46        }
47}
48
49namespace db
50{
51        user::user(std::string userid,
52                   boost::shared_ptr<db> dbase,
53                   boost::shared_ptr<password_handler> pwh)
54                : userid(userid)
55                , do_allow_cleartext_password(false)
56                , delivery_email_verified(false)
57                , dbase(dbase)
58                , pwh(pwh)
59        {
60                roles.insert(role::authn());
61        }
62
63        void user::set_display_name(std::string new_name)
64        {
65                if (new_name == display_name) return;
66                std::ostringstream os;
67                os << "USER "
68                   << userid
69                   << "\ndisplay_name "
70                   << new_name
71                   << "\n";
72                dbase->add_record(os.str());
73                BOOST_ASSERT(display_name == new_name);
74        }
75        void user::set_display_email(std::string new_addr)
76        {
77                if (new_addr == display_email) return;
78                std::ostringstream os;
79                os << "USER "
80                   << userid
81                   << "\ndisplay_email "
82                   << new_addr
83                   << "\n";
84                dbase->add_record(os.str());
85                BOOST_ASSERT(display_email == new_addr);
86        }
87        bool user::set_delivery_email(std::string new_addr)
88        {
89                if (new_addr == delivery_email) return false;
90                std::string token = mktoken();
91                std::ostringstream os;
92                os << "USER "
93                   << userid
94                   << "\ndelivery_email "
95                   << new_addr
96                   << "\ndelivery_email_verified no"
97                   << "\ndelivery_email_cookie "
98                   << token
99                   << "\n";
100                dbase->add_record(os.str());
101                BOOST_ASSERT(delivery_email == new_addr);
102                BOOST_ASSERT(!delivery_email_verified);
103                BOOST_ASSERT(delivery_email_cookie == token);
104                return true;
105        }
106        void user::set_allow_cleartext_password(bool val)
107        {
108                if (val == do_allow_cleartext_password) return;
109                std::ostringstream os;
110                os << "USER "
111                   << userid
112                   << "\nallow_cleartext_password "
113                   << (val ? "yes" : "no")
114                   << "\n";
115                dbase->add_record(os.str());
116                BOOST_ASSERT(do_allow_cleartext_password == val);
117        }
118        void user::send_delivery_email_cookie(server::conn_cb cb,
119                                              std::string request_ip)
120        {
121                if (delivery_email_cookie == "")
122                {
123                        std::string token = mktoken();
124                        std::ostringstream os;
125                        os << "USER "
126                           << userid
127                           << "\ndelivery_email_cookie "
128                           << token
129                           << "\n";
130                        dbase->add_record(os.str());
131                        BOOST_ASSERT(delivery_email_cookie == token);
132                }
133                std::string ton = display_name;
134                std::string to = delivery_email;
135                std::string from =
136                        config["alue-name"].as<std::string>() +
137                        " <" +
138                        config["operator-email"].as<std::string>() +
139                        ">";
140
141                std::ostringstream link;
142                link << "https://"
143                     << config["canonical-name"].as<std::string>()
144                     << (config["https-port"].as<std::string>() == "443"
145                         ? ""
146                         : ":" + config["https-port"].as<std::string>())
147                     << "/confirm/"
148                     << uri::percent_encode(delivery_email_cookie);
149
150                tlate::data_model::ptr mam(new tlate::data_model);
151
152                mam->insert("from", from);
153                mam->insert("to",
154                            ::msg::make_phrase(ton) + " <" + to + ">");
155                mam->insert("user", new tlate::user_value(shared_from_this()));
156                mam->insert("link", link.str());
157                mam->insert("request_ip", request_ip);
158               
159                boost::shared_ptr<tlate::tlate> tl =
160                        tlate::tlate::parse("confirm.msg");
161                std::ostringstream mos;
162                mos << tl->eval(mam);
163                       
164                std::list<std::string> recv;
165                recv.push_back(to);
166                               
167                cb.smtpc().send_mail(recv, mos.str());
168        }
169        bool user::verify_delivery_email(std::string cookie, server::conn_cb cb)
170        {
171                if (delivery_email_verified) return true;
172                if (cookie == "") return false;
173                if (delivery_email_cookie != cookie) return false;
174                std::ostringstream os;
175                os << "USER "
176                   << userid
177                   << "\ndelivery_email_verified yes"
178                   << "\n";
179                dbase->add_record(os.str());
180                BOOST_ASSERT(delivery_email_verified);
181
182                tlate::data_model::ptr mam(new tlate::data_model);
183
184                std::string ton = display_name;
185                std::string to = delivery_email;
186                std::string from =
187                        config["alue-name"].as<std::string>() +
188                        " <" +
189                        config["operator-email"].as<std::string>() +
190                        ">";
191                mam->insert("from", from);
192                mam->insert("to",
193                            ::msg::make_phrase(ton) + " <" + to + ">");
194                mam->insert("user", new tlate::user_value(shared_from_this()));
195
196                boost::shared_ptr<tlate::tlate> tl =
197                        tlate::tlate::parse("confirmed.msg");
198                std::ostringstream mos;
199                mos << tl->eval(mam);
200                       
201                std::list<std::string> recv;
202                recv.push_back(to);
203                               
204                cb.smtpc().send_mail(recv, mos.str());
205
206                return true;
207        }
208
209        void user::add_role(boost::shared_ptr<role> r)
210        {
211                if (roles.find(r) != roles.end()) return;
212
213                std::ostringstream os;
214                os << "ROLE "
215                   << r->get_name()
216                   << "\r\n"
217                   << "USER ADD " + userid;
218                dbase->add_record(os.str());
219                BOOST_ASSERT(roles.find(r) != roles.end());
220                BOOST_ASSERT(r->users.find(shared_from_this())!=r->users.end());
221        }
222
223        void user::delete_role(boost::shared_ptr<role> r)
224        {
225                if (roles.find(r) == roles.end()) return;
226                std::ostringstream os;
227                os << "ROLE "
228                   << r->get_name()
229                   << "\r\n"
230                   << "USER DEL " + userid;
231                dbase->add_record(os.str());
232                BOOST_ASSERT(roles.find(r) == roles.end());
233                BOOST_ASSERT(r->users.find(shared_from_this())==r->users.end());
234        }
235
236        void user::mark_read(std::string msgid)
237        {
238                if (has_read(msgid)) return;
239                std::ostringstream os;
240                os << "USER " << userid << "\r\n"
241                   << "has_read " << msgid;
242                dbase->add_record(os.str());
243                BOOST_ASSERT(has_read(msgid));
244        }
245        void user::unmark_read(std::string msgid)
246        {
247                if (!has_read(msgid)) return;
248                std::ostringstream os;
249                os << "USER " << userid << "\r\n"
250                   << "has_not_read " << msgid;
251                dbase->add_record(os.str());
252                BOOST_ASSERT(!has_read(msgid));
253        }
254
255        bool user::is_group_moderator(std::string grn) const
256        {
257                for (std::set<role::ptr>::const_iterator it = roles.begin();
258                     it != roles.end(); it++)
259                {
260                        role::ptr r = *it;
261                        if (r->is_moderator_for(grn)) return true;
262                }
263                return false;
264        }
265
266        bool user::is_moderator(boost::shared_ptr<const group> gr) const
267        {
268                return is_group_moderator(gr->name());
269        }
270
271        bool user::is_moderator(boost::shared_ptr<const msg> m) const
272        {
273                std::list<std::string> ngs = m->get_newsgroups();
274                for (std::list<std::string>::const_iterator it = ngs.begin();
275                     it != ngs.end(); it++)
276                {
277                        if (is_group_moderator(*it)) return true;
278                }
279                return false;
280        }
281
282}
Note: See TracBrowser for help on using the browser.