Changeset 2114058982a08f59f0f312544a16250eceab0098

Show
Ignore:
Timestamp:
01/09/11 21:00:35 (17 months ago)
Author:
Antti-Juhani Kaijanaho <antti-juhani@…>
Children:
cbc895b6da7a6196ef0422747bd7dec2a40551d5
Parents:
0062266a64c1492ae732d9e77d88016547e82c16
git-author:
Antti-Juhani Kaijanaho <antti-juhani@…> (01/09/11 21:00:21)
git-committer:
Antti-Juhani Kaijanaho <antti-juhani@…> (01/09/11 21:00:35)
Message:

#14: Support moderators with kill/mark-as-spam and resurrection powers

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

Files:
1 added
12 modified

Legend:

Unmodified
Added
Removed
  • db/FORMAT.txt

    rba71d64 r2114058  
    6969 
    7070NOTE: The following role names are reserved: anonymous, authenticated, 
    71 poster.  Similarly, all names starting with "subscribers:" are 
    72 reserved.  No ROLE records may be given for "anonymous" and 
    73 "authenticated".  ROLE records for the other reserved names are 
    74 forbidden to include DESCRIPTION. 
     71poster.  Similarly, all names starting with "subscribers:" and 
     72"moderator:" are reserved.  No ROLE records may be given for 
     73"anonymous" and "authenticated".  ROLE records for the other reserved 
     74names are forbidden to include DESCRIPTION. 
    7575 
    7676 
     
    111111 
    112112 
     113                          MODERATION records 
     114 
     115.BEGIN <datetime> 
     116MODERATION <userid> 
     117<verb> <msgid> <reason> 
     118.END 
     119 
     120<verb> ::= KILL 
     121         | SPAM 
     122         | CLEAR 
     123 
     124<reason> ::= <text not containing line terminator or separator> 
     125 
     126The MODERATION line is REQUIRED and MUST NOT be repeated.  The other 
     127lines MAY occur multiple times.  The <userid> indicates the user who 
     128authorized these moderation actions. 
     129 
     130The effect of a KILL or SPAM line is to make the message disappear 
     131(the reason is free form text that is intended to be used as 
     132rationale); it will be as if it never existed.  The effect of a CLEAR 
     133line is to undo a previous KILL or SPAM line. 
  • db/db.cc

    rba71d64 r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    182182        } 
    183183 
     184        void db::do_moderation(db_reader &dr, std::string line) 
     185        { 
     186                std::string uid = line; 
     187                util::strip(uid); 
     188                user::ptr u = users[uid]; 
     189                if (!u) throw illformed_db("MODERATION user invalid: " + uid); 
     190                while (true) 
     191                { 
     192                        dr.readline(line); 
     193                        if (line == ".END" || line == ".END\r") break; 
     194                        std::string keys = util::split(line); 
     195                        std::string mid = util::split(line); 
     196                        std::string reason = line; 
     197                        msg::ptr m = msgid[mid]; 
     198                        if (!m) 
     199                        { 
     200                                logger::logline ll; 
     201                                ll << "unknown message in MODERATION ignored: " 
     202                                   << keys << " " << mid; 
     203                                continue; 
     204                        } 
     205                        msg::moderation::kind_type key; 
     206                        /**/ if (keys == "KILL")  key = msg::moderation::KILL; 
     207                        else if (keys == "SPAM")  key = msg::moderation::SPAM; 
     208                        else if (keys == "CLEAR") key = msg::moderation::CLEAR; 
     209                        else throw illformed_db("MODERATION key error: " + 
     210                                                keys); 
     211                        m->moderate(msg::moderation(key, u, reason)); 
     212                } 
     213        } 
     214 
    184215        void db::do_article(db_reader &dr, std::string line) 
    185216        { 
     
    272303                else if (cmd == "ARTICLE") 
    273304                        do_article(dr, line); 
     305                else if (cmd == "MODERATION") 
     306                        do_moderation(dr, line); 
    274307                else 
    275308                        throw illformed_db("unrecognized record type " + cmd); 
  • db/db.hh

    r1a970cd r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    137137                void do_article(db_reader &, std::string); 
    138138                void do_role(db_reader &, std::string); 
     139                void do_moderation(db_reader &, std::string); 
    139140                void read_record(db_reader &dr, boost::posix_time::ptime); 
    140141                void register_role(boost::shared_ptr<role>); 
  • db/msg.hh

    rba71d64 r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    3939        { 
    4040        public: 
     41                struct moderation 
     42                { 
     43                        const enum kind_type { CLEAR, KILL, SPAM } kind; 
     44                        const boost::shared_ptr<const user> u; 
     45                        const std::string reason; 
     46 
     47                        moderation(kind_type k, 
     48                                   boost::shared_ptr<const user> u, 
     49                                   std::string reason) 
     50                                : kind(k) 
     51                                , u(u) 
     52                                , reason(reason) 
     53                                {} 
     54 
     55                        bool is_censure() const { return kind != CLEAR; } 
     56                }; 
     57 
    4158                typedef boost::shared_ptr<msg> ptr; 
    4259                typedef boost::shared_ptr<const msg> const_ptr; 
     
    5168                explicit msg(boost::shared_ptr< ::msg::entity >, 
    5269                             boost::shared_ptr<user>); 
     70 
     71                void moderate(moderation m) { mods.push_back(m); } 
     72 
     73                bool is_censured() const  
     74                        { return !mods.empty() && mods.back().is_censure(); } 
     75 
     76                boost::shared_ptr<const user> censor() const { 
     77                        boost::shared_ptr<const user> rv; 
     78                        if (!mods.empty()) rv = mods.back().u; 
     79                        return rv; 
     80                } 
     81 
     82                const std::list<moderation> &get_moderations() const 
     83                        { return mods; } 
    5384 
    5485                boost::shared_ptr<const ::msg::entity> get_entity() const 
     
    79110                boost::shared_ptr< ::msg::entity > actual; 
    80111                boost::shared_ptr<user> poster; 
     112                std::list<moderation> mods; 
    81113        }; 
    82114         
  • db/role.cc

    re1af652 r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    1919 
    2020#include "role.hh" 
     21#include "../nntp/wildmat.hh" 
    2122 
    2223namespace db 
    2324{ 
    2425        const std::string role::subscriber_prefix = "subscribers:"; 
     26        const std::string role::moderator_prefix = "moderator:"; 
     27 
     28        bool role::is_moderator_for(std::string grn) 
     29        { 
     30                if (!is_moderator()) return false; 
     31                std::string mg = name.substr(moderator_prefix.length()); 
     32                if (!nntp::is_wildmat(mg)) return false; 
     33                return nntp::wildmatch(mg, grn); 
     34        } 
    2535} 
  • db/role.hh

    r4c34ee2 r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    4040 
    4141                static const std::string subscriber_prefix; 
     42                static const std::string moderator_prefix; 
    4243        public: 
    4344                typedef boost::shared_ptr<role> ptr; 
     
    5051                std::string get_name() const { return name; } 
    5152                std::string get_description() const { return name; } 
     53 
     54                bool is_moderator() { 
     55                        return  name.substr(0, moderator_prefix.length()) 
     56                                == 
     57                                moderator_prefix; 
     58                } 
     59                bool is_moderator_for(std::string grn); 
    5260 
    5361                const std::set<boost::shared_ptr<user> > &get_users() const { 
  • db/user.cc

    r1a970cd r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    227227        } 
    228228 
     229        bool user::is_group_moderator(std::string grn) const 
     230        { 
     231                for (std::set<role::ptr>::const_iterator it = roles.begin(); 
     232                     it != roles.end(); it++) 
     233                { 
     234                        role::ptr r = *it; 
     235                        if (r->is_moderator_for(grn)) return true; 
     236                } 
     237                return false; 
     238        } 
     239 
     240        bool user::is_moderator(boost::shared_ptr<const group> gr) const 
     241        { 
     242                return is_group_moderator(gr->name()); 
     243        } 
     244 
     245        bool user::is_moderator(boost::shared_ptr<const msg> m) const 
     246        { 
     247                std::list<std::string> ngs = m->get_newsgroups(); 
     248                for (std::list<std::string>::const_iterator it = ngs.begin(); 
     249                     it != ngs.end(); it++) 
     250                { 
     251                        if (is_group_moderator(*it)) return true; 
     252                } 
     253                return false; 
     254        } 
     255 
    229256} 
  • db/user.hh

    r563ece2 r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    3333{ 
    3434        class db; 
     35        class group; 
     36        class msg; 
    3537        class role; 
    3638 
     
    5254 
    5355                std::set<std::string> read_msgids; 
     56 
     57                bool is_group_moderator(std::string) const; 
    5458 
    5559                friend class db; 
     
    108112                void unmark_read(std::string msgid); 
    109113 
     114                bool is_moderator(boost::shared_ptr<const group> gr) const; 
     115                bool is_moderator(boost::shared_ptr<const msg> m) const; 
     116 
    110117                static std::string passwd_problems(std::string pw) { 
    111118                        std::string err; 
  • nntp/article.cc

    r1a970cd r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    140140                } 
    141141 
     142                if (message->is_censured()) 
     143                { 
     144                        switch (state) { 
     145                        case NUMBER: 
     146                                c.send_line("423 no such article"); 
     147                                break; 
     148                        case MSGID: 
     149                                c.send_line("430 no such article"); 
     150                                break; 
     151                        case NONE: 
     152                                if (c.current_article() == 0) 
     153                                        c.send_line("420 no such article"); 
     154                                else 
     155                                        c.send_line("423 no such article"); 
     156                                break; 
     157                        } 
     158                        return c.dispatch(); 
     159                } 
     160 
    142161                std::string msgparm = msgnum + " " + message->msgid(); 
    143162 
  • nntp/hdr.cc

    r1a970cd r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    8484                                        return c.dispatch(); 
    8585                                } 
     86                                if (m->is_censured()) 
     87                                { 
     88                                        c.send_line("430 no such article"); 
     89                                        return c.dispatch(); 
     90                                } 
     91 
    8692 
    8793                                c.send_line("221 " + hname + " follows:"); 
     
    133139                if (!m->reading_authz(c.identity())) 
    134140                        return; 
     141                if (m->is_censured()) return; 
    135142 
    136143                std::string hn = util::to_lower(hname); 
  • nntp/over.cc

    r1a970cd r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    8585                                        return c.dispatch(); 
    8686                                } 
     87                                if (m->is_censured()) 
     88                                { 
     89                                        c.send_line("430 no such article"); 
     90                                        return c.dispatch(); 
     91                                } 
    8792                                c.send_line("221 overview follows:"); 
    8893                                write_article_line(c, 0, m); 
     
    139144                if (!m->reading_authz(c.identity())) 
    140145                        return; 
     146                if (m->is_censured()) return; 
    141147                std::ostringstream os; 
    142148                os << artnum; 
  • tlate/msg_value.cc

    rba71d64 r2114058  
    11/*  This file is part of Alue, the multiprotocol Internet discussion daemon 
    22 
    3     Copyright © 2009, 2010 Antti-Juhani Kaijanaho 
     3    Copyright © 2009, 2010, 2011 Antti-Juhani Kaijanaho 
    44 
    55    Alue is free software: you can redistribute it and/or modify it 
     
    135135                std::string msgid = tn->get_msgid(); 
    136136                bool rauthz = m ? m->reading_authz(u) : false; 
     137                bool show = rauthz && !m->is_censured(); 
    137138                bool authn = u; 
    138139                value::const_ptr rv; 
     
    151152                                              uri::percent_encode(msgid), 
    152153                                              false))); 
    153                 else if (var == "followup-allowed" && m->posting_authz(u)) 
     154                else if (var == "followup-allowed" && 
     155                         m->posting_authz(u) && show) 
    154156                        rv.reset(new sv(http::compose::get_followup_uri(m))); 
    155                 else if (var == "followup-uri") 
     157                else if (var == "followup-uri" && show) 
    156158                        rv.reset(new sv(http::compose::get_followup_uri(m))); 
    157159                else if (!rauthz && var == "restricted") 
    158160                        rv.reset(new empty_value); 
    159                 else if (rauthz && m && var == "from") 
     161                else if (show && m && var == "from") 
    160162                        rv.reset(new sv(quote(decode_unstructured 
    161163                                              (e->get_field("From", false)), 
    162164                                              !authn))); 
    163                 else if (rauthz && m && var == "subject") 
     165                else if (show && m && var == "subject") 
    164166                        rv.reset(new sv(quote(decode_unstructured 
    165167                                              (e->get_field("Subject", false)), 
     
    171173                        rv.reset(new date_value((tn->get_latest_date()))); 
    172174                                                 
    173                 else if (rauthz && m && var == "header") 
     175                else if (show && m && var == "header") 
    174176                        rv.reset(new header_value(e,!u)); 
    175                 else if (rauthz && m && var == "body") 
     177                else if (show && m && var == "body") 
    176178                        rv = e->get_tlate_value(authn); 
    177179                else if (rauthz && m && var == "xref") 
     
    203205                else if (u && var == "marked_read" && u->has_read(msgid)) 
    204206                        rv.reset(new empty_value); 
    205                 else if (u && rauthz && m && var == "poster" && m->get_poster()) 
     207                else if (u && show && m && var == "poster" && m->get_poster()) 
    206208                        rv.reset(new user_value(m->get_poster())); 
     209                else if (u && rauthz && m && var == "own" && 
     210                         m->get_poster() == u) 
     211                        rv.reset(new empty_value); 
     212                else if (rauthz && m->is_censured() && var == "moderated") 
     213                        rv.reset(new empty_value); 
     214                else if (rauthz && m && var == "moderator") 
     215                { 
     216                        db::user::const_ptr u = m->censor(); 
     217                        if (u) rv.reset(new user_value(u)); 
     218                } 
     219                else if (u && m && var == "mod-uri" && u->is_moderator(m)) 
     220                        rv.reset(new sv(quote("/mod", false))); 
    207221                return rv; 
    208222        }