| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 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 | |
|---|
| 34 | namespace |
|---|
| 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"; |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | return token; |
|---|
| 46 | } |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | namespace 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 | } |
|---|