| 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 "group.hh" |
|---|
| 22 | #include "role.hh" |
|---|
| 23 | #include "user.hh" |
|---|
| 24 | |
|---|
| 25 | #include "../config.hh" |
|---|
| 26 | #include "../msg/entity.hh" |
|---|
| 27 | #include "../msg/multipart.hh" |
|---|
| 28 | #include "../msg/lexutils.hh" |
|---|
| 29 | #include "../msg/text_plain.hh" |
|---|
| 30 | #include "../smtp_client/smtp_client.hh" |
|---|
| 31 | #include "../tlate/data_model.hh" |
|---|
| 32 | #include "../tlate/group_value.hh" |
|---|
| 33 | #include "../tlate/user_value.hh" |
|---|
| 34 | #include "../tlate/tlate.hh" |
|---|
| 35 | |
|---|
| 36 | #include "../assert.hh" |
|---|
| 37 | |
|---|
| 38 | namespace db |
|---|
| 39 | { |
|---|
| 40 | group::group(std::string name, |
|---|
| 41 | boost::shared_ptr<db> dbase, |
|---|
| 42 | boost::posix_time::ptime stamp, |
|---|
| 43 | bool reading_restricted, std::string descr) |
|---|
| 44 | : the_name(name), stamp(stamp), |
|---|
| 45 | descr(descr), |
|---|
| 46 | dbase(dbase), |
|---|
| 47 | count(0), displacement(1) |
|---|
| 48 | { |
|---|
| 49 | if (!reading_restricted) readers.insert(role::anon()); |
|---|
| 50 | readers.insert(role::authn()); |
|---|
| 51 | posters.insert(role::poster()); |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | group::number group::file(boost::shared_ptr<msg::msg> m, |
|---|
| 56 | server::conn_cb cb) |
|---|
| 57 | { |
|---|
| 58 | msgs.push_back(m); |
|---|
| 59 | number rv = displacement + msgs.size() - 1; |
|---|
| 60 | m->xref(shared_from_this(), rv); |
|---|
| 61 | count++; |
|---|
| 62 | |
|---|
| 63 | ensure_subscriber_role(); |
|---|
| 64 | const std::set<boost::shared_ptr<user> > &us = |
|---|
| 65 | subscriber_role->get_users(); |
|---|
| 66 | std::list<std::string> recv; |
|---|
| 67 | for (std::set<boost::shared_ptr<user> >::const_iterator it = |
|---|
| 68 | us.begin(); |
|---|
| 69 | it != us.end(); it++) |
|---|
| 70 | { |
|---|
| 71 | user::ptr u = *it; |
|---|
| 72 | if (!u->is_delivery_email_verified()) continue; |
|---|
| 73 | recv.push_back(u->get_delivery_email()); |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | if (recv.empty()) return rv; |
|---|
| 77 | |
|---|
| 78 | ::msg::multipart::ptr nm = |
|---|
| 79 | m->get_entity()->clone_as_multipart(); |
|---|
| 80 | { |
|---|
| 81 | std::string subject = nm->get_field("subject", false); |
|---|
| 82 | util::strip_crlf(subject); |
|---|
| 83 | std::string tag = "["; tag += the_name; tag += "]"; |
|---|
| 84 | if (subject.find(tag) == std::string::npos) |
|---|
| 85 | nm->replace_field("Subject", |
|---|
| 86 | tag + " " + subject); |
|---|
| 87 | } |
|---|
| 88 | nm->replace_field("To", |
|---|
| 89 | name() + "@" + |
|---|
| 90 | config["canonical-name"].as<std::string>()); |
|---|
| 91 | nm->replace_field("List-Id", |
|---|
| 92 | "<" + |
|---|
| 93 | name() + "." + |
|---|
| 94 | config["canonical-name"].as<std::string>() + |
|---|
| 95 | ">"); |
|---|
| 96 | |
|---|
| 97 | tlate::data_model::ptr mam(new tlate::data_model); |
|---|
| 98 | mam->insert("group", new tlate::group_value(shared_from_this(), |
|---|
| 99 | user::ptr())); |
|---|
| 100 | |
|---|
| 101 | boost::shared_ptr<tlate::tlate> tl = |
|---|
| 102 | tlate::tlate::parse("sub_footer.txt"); |
|---|
| 103 | std::ostringstream mos; |
|---|
| 104 | mos << tl->eval(mam); |
|---|
| 105 | ::msg::text_plain::ptr sub(new ::msg::text_plain |
|---|
| 106 | (mos.str(), |
|---|
| 107 | ::msg::content_type(DEFAULT_CT))); |
|---|
| 108 | nm->append_part(sub); |
|---|
| 109 | |
|---|
| 110 | cb.smtpc().send_mail(recv, nm->get_entity()); |
|---|
| 111 | |
|---|
| 112 | return rv; |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | void group::file(boost::shared_ptr<msg::msg> m, number n) |
|---|
| 116 | { |
|---|
| 117 | assert(n >= displacement); |
|---|
| 118 | if (msgs.empty()) displacement = n; |
|---|
| 119 | size_t n_ = n - displacement; |
|---|
| 120 | if (n_ >= msgs.size()) msgs.resize(n_+1); |
|---|
| 121 | msgs[n_] = m; |
|---|
| 122 | m->xref(shared_from_this(), n); |
|---|
| 123 | count++; |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | bool group::authz(boost::shared_ptr<const user> u, |
|---|
| 127 | const std::set<role::ptr> & rs) |
|---|
| 128 | { |
|---|
| 129 | if (!u) return rs.find(role::anon()) != rs.end(); |
|---|
| 130 | const std::set<role::ptr> & urs = u->get_roles(); |
|---|
| 131 | for (std::set<role::ptr>::const_iterator it |
|---|
| 132 | = urs.begin(); |
|---|
| 133 | it != urs.end(); it++) |
|---|
| 134 | { |
|---|
| 135 | if (rs.find(*it) != rs.end()) return true; |
|---|
| 136 | } |
|---|
| 137 | return false; |
|---|
| 138 | } |
|---|
| 139 | void group::ensure_subscriber_role() |
|---|
| 140 | { |
|---|
| 141 | if (subscriber_role) return; |
|---|
| 142 | |
|---|
| 143 | std::string subrn = role::get_subscriber_role(the_name); |
|---|
| 144 | subscriber_role = dbase->lookup_role(subrn); |
|---|
| 145 | if (!subscriber_role) |
|---|
| 146 | { |
|---|
| 147 | subscriber_role = dbase->create_role(subrn, ""); |
|---|
| 148 | } |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | void group::send_submail(user::const_ptr u, const char *tln, |
|---|
| 152 | server::conn_cb cb) |
|---|
| 153 | { |
|---|
| 154 | std::string ton = u->get_display_name(); |
|---|
| 155 | std::string to = u->get_delivery_email(); |
|---|
| 156 | std::string from = |
|---|
| 157 | config["alue-name"].as<std::string>() + |
|---|
| 158 | " <" + |
|---|
| 159 | config["operator-email"].as<std::string>() + |
|---|
| 160 | ">"; |
|---|
| 161 | |
|---|
| 162 | tlate::data_model::ptr mam(new tlate::data_model); |
|---|
| 163 | mam->insert("from", from); |
|---|
| 164 | mam->insert("to", |
|---|
| 165 | ::msg::make_phrase(ton) + " <" + to + ">"); |
|---|
| 166 | mam->insert("user", new tlate::user_value(u)); |
|---|
| 167 | mam->insert("group", |
|---|
| 168 | new tlate::group_value(shared_from_this(), u)); |
|---|
| 169 | |
|---|
| 170 | boost::shared_ptr<tlate::tlate> tl = tlate::tlate::parse(tln); |
|---|
| 171 | std::ostringstream mos; |
|---|
| 172 | mos << tl->eval(mam); |
|---|
| 173 | |
|---|
| 174 | std::list<std::string> recv; |
|---|
| 175 | recv.push_back(to); |
|---|
| 176 | |
|---|
| 177 | cb.smtpc().send_mail(recv, mos.str()); |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | void group::add_subscriber(boost::shared_ptr<user> u, |
|---|
| 181 | server::conn_cb cb, |
|---|
| 182 | boost::asio::ip::address peer) |
|---|
| 183 | { |
|---|
| 184 | BOOST_ASSERT(u); |
|---|
| 185 | ensure_subscriber_role(); |
|---|
| 186 | u->add_role(subscriber_role); |
|---|
| 187 | if (!u->is_delivery_email_verified()) |
|---|
| 188 | u->send_delivery_email_cookie |
|---|
| 189 | (cb, peer.to_string()); |
|---|
| 190 | else |
|---|
| 191 | send_submail(u, "sub.msg", cb); |
|---|
| 192 | } |
|---|
| 193 | void group::delete_subscriber(boost::shared_ptr<user> u, |
|---|
| 194 | server::conn_cb cb) |
|---|
| 195 | { |
|---|
| 196 | ensure_subscriber_role(); |
|---|
| 197 | u->delete_role(subscriber_role); |
|---|
| 198 | if (u->is_delivery_email_verified()) |
|---|
| 199 | send_submail(u, "unsub.msg", cb); |
|---|
| 200 | } |
|---|
| 201 | bool group::is_subscriber(boost::shared_ptr<const user> u) |
|---|
| 202 | { |
|---|
| 203 | if (!u) return false; |
|---|
| 204 | ensure_subscriber_role(); |
|---|
| 205 | const std::set<boost::shared_ptr<role> > &rs = u->get_roles(); |
|---|
| 206 | return rs.find(subscriber_role) != rs.end(); |
|---|
| 207 | } |
|---|
| 208 | } |
|---|