Beispiel #1
0
    def get_authenticated_account(self):
        from v1.models import Account, NotFound, register

        try:
            authorization = request.environ.get("HTTP_AUTHORIZATION")
            username, password = parse_http_basic(authorization)
        except RequirementException:
            return None

        try:
            account = Account._by_name(username)
        except NotFound:
            if g.auth_trust_http_authorization:
                # note: we're explicitly allowing automatic re-registration of
                # _deleted accounts and login of _banned accounts here because
                # we're trusting you know what you're doing in an SSO situation
                account = register(username, password, request.ip)
            else:
                return None

        # if we're to trust the authorization headers, don't check passwords
        if g.auth_trust_http_authorization:
            return account

        # not all systems support bcrypt in the standard crypt
        if account.password.startswith("$2a$"):
            expected_hash = bcrypt.hashpw(password, account.password)
        else:
            expected_hash = crypt.crypt(password, account.password)

        if not constant_time_compare(expected_hash, account.password):
            return None
        return account
Beispiel #2
0
    def _gift_using_cverbifys(self,
                              recipient,
                              months=1,
                              thing_fullname=None,
                              proxying_for=None):
        with cverbifys_lock(c.user):
            if not c.user.employee and c.user.sodium_cverbifys < months:
                err = VerbifyError("INSUFFICIENT_CVERBIFYS")
                self.on_validation_error(err)

            note = None
            buyer = c.user
            if c.user.name.lower() in g.live_config["proxy_silding_accounts"]:
                note = "proxy-%s" % c.user.name
                if proxying_for:
                    try:
                        buyer = Account._by_name(proxying_for)
                    except NotFound:
                        pass

            send_gift(
                buyer=buyer,
                recipient=recipient,
                months=months,
                days=months * 31,
                signed=False,
                giftmessage=None,
                thing_fullname=thing_fullname,
                note=note,
            )

            if not c.user.employee:
                c.user.sodium_cverbifys -= months
                c.user._commit()
Beispiel #3
0
def monitor_mentions(comment):
    if comment._spam or comment._deleted:
        return

    sender = comment.author_slow
    if getattr(sender, "butler_ignore", False):
        # this is an account that generates false notifications, e.g.
        # LinkFixer
        return

    if sender.in_timeout:
        return

    subverbify = comment.subverbify_slow
    usernames = extract_user_mentions(comment.body)
    inbox_class = Inbox.rel(Account, Comment)

    # If more than our allowed number of mentions were passed, don't highlight
    # any of them.
    if len(usernames) > g.butler_max_mentions:
        return

    # Subverbify.can_view stupidly requires this.
    c.user_is_loggedin = True

    for username in usernames:
        try:
            account = Account._by_name(username)
        except NotFound:
            continue

        # most people are aware of when they mention themselves.
        if account == sender:
            continue

        # bail out if that user has the feature turned off
        if not account.pref_monitor_mentions:
            continue

        # don't notify users of things they can't see
        if not subverbify.can_view(account):
            continue

        # don't notify users when a person they've blocked mentions them
        if account.is_enemy(sender):
            continue

        # ensure this comment isn't already in the user's inbox already
        rels = inbox_class._fast_query(
            account,
            comment,
            ("inbox", "selfreply", "mention"),
        )
        if filter(None, rels.values()):
            continue

        notify_mention(account, comment)
Beispiel #4
0
def ensure_account(name):
    """Look up or register an account and return it."""
    try:
        account = Account._by_name(name)
        print ">> found /u/{}".format(name)
        return account
    except NotFound:
        print ">> registering /u/{}".format(name)
        return register(name, "password", "127.0.0.1")
Beispiel #5
0
    def get_reports(cls, wrapped, max_user_reasons=20):
        """Get two lists of mod and user reports on the item."""
        if (wrapped.reported > 0 and
            (wrapped.can_ban
             or getattr(wrapped, "promoted", None) and c.user_is_sponsor)):
            from v1.models import SRMember

            reports = cls.for_thing(wrapped.lookups[0])

            query = SRMember._query(SRMember.c._thing1_id == wrapped.sr_id,
                                    SRMember.c._name == "moderator")
            mod_dates = {rel._thing2_id: rel._date for rel in query}

            if g.automoderator_account:
                automoderator = Account._by_name(g.automoderator_account)
            else:
                automoderator = None

            mod_reports = []
            user_reports = []

            for report in reports:
                # always include AutoModerator reports
                if automoderator and report._thing1_id == automoderator._id:
                    mod_reports.append(report)
                # include in mod reports if made after the user became a mod
                elif (report._thing1_id in mod_dates
                      and report._date >= mod_dates[report._thing1_id]):
                    mod_reports.append(report)
                else:
                    user_reports.append(report)

            # mod reports return as tuples with (reason, name)
            mods = Account._byID([report._thing1_id for report in mod_reports],
                                 data=True,
                                 return_dict=True)
            mod_reports = [(getattr(report, "reason",
                                    None), mods[report._thing1_id].name)
                           for report in mod_reports]

            # user reports return as tuples with (reason, count)
            user_reports = Counter(
                [getattr(report, "reason", None) for report in user_reports])
            user_reports = user_reports.most_common(max_user_reasons)

            return mod_reports, user_reports
        else:
            return [], []
Beispiel #6
0
    def POST_zendeskreply(self):
        request_body = request.POST
        recipient = request_body["recipient"]
        sender_email = request_body["sender"]
        from_ = request_body["from"]
        subject = request_body["subject"]
        body_plain = request_body["body-plain"]
        stripped_text = request_body["stripped-text"]
        timestamp = request_body["timestamp"]
        token = request_body["token"]
        signature = request_body["signature"]
        email_id = request_body["Message-Id"]

        if not validate_mailgun_webhook(timestamp, token, signature):
            # per Mailgun docs send a 406 so the message won't be retried
            abort(406, "invalid signature")

        message_id36 = parse_and_validate_reply_to_address(recipient)

        if not message_id36:
            # per Mailgun docs send a 406 so the message won't be retried
            abort(406, "invalid message")

        parent = Message._byID36(message_id36, data=True)
        to = Account._byID(parent.author_id, data=True)
        sr = Subverbify._byID(parent.sr_id, data=True)

        if stripped_text.startswith(ZENDESK_PREFIX):
            stripped_text = stripped_text[len(ZENDESK_PREFIX):].lstrip()

        if len(stripped_text) > 10000:
            body = stripped_text[:10000] + "\n\n--snipped--"
        else:
            body = stripped_text

        try:
            markdown_souptest(body)
        except SoupError:
            g.log.warning("bad markdown in modmail email: %s", body)
            abort(406, "invalid body")

        if parent.get_muted_user_in_conversation():
            queue_blocked_muted_email(sr, parent, sender_email, email_id)
            return

        # keep the subject consistent
        message_subject = parent.subject
        if not message_subject.startswith("re: "):
            message_subject = "re: " + message_subject

        # from_ is like '"NAME (GROUP)" <*****@*****.**>'
        match = re.search("\"(?P<name>\w+) [\w ()]*\"", from_)
        from_sr = True
        author = Account.system_user()

        if match and match.group(
                "name") in g.live_config['modmail_account_map']:
            zendesk_name = match.group("name")
            moderator_name = g.live_config['modmail_account_map'][zendesk_name]
            moderator = Account._by_name(moderator_name)
            if sr.is_moderator_with_perms(moderator, "mail"):
                author = moderator
                from_sr = False

        message, inbox_rel = Message._new(
            author=author,
            to=to,
            subject=message_subject,
            body=body,
            ip='0.0.0.0',
            parent=parent,
            sr=sr,
            from_sr=from_sr,
            can_send_email=False,
            sent_via_email=True,
            email_id=email_id,
        )
        message._commit()
        queries.new_message(message, inbox_rel)
        g.stats.simple_event("mailgun.incoming.success")
        g.stats.simple_event("modmail_email.incoming_email")