mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-22 21:38:11 -05:00
Add alerts for suspicious selfserve advertising payments.
This commit is contained in:
committed by
David Wick
parent
6b3f4b69de
commit
b76322f8e4
@@ -977,18 +977,20 @@ class PromoteApiController(ApiController):
|
||||
rc = RenderableCampaign.from_campaigns(link, campaign)
|
||||
jquery.update_campaign(campaign._fullname, rc.render_html())
|
||||
|
||||
@validatedForm(VSponsor('link'),
|
||||
VModhash(),
|
||||
link=VByName("link"),
|
||||
campaign=VPromoCampaign("campaign"),
|
||||
customer_id=VInt("customer_id", min=0),
|
||||
pay_id=VInt("account", min=0),
|
||||
edit=VBoolean("edit"),
|
||||
address=ValidAddress(
|
||||
["firstName", "lastName", "company", "address",
|
||||
"city", "state", "zip", "country", "phoneNumber"]),
|
||||
creditcard=ValidCard(["cardNumber", "expirationDate",
|
||||
"cardCode"]))
|
||||
@validatedForm(
|
||||
VSponsor('link'),
|
||||
VModhash(),
|
||||
link=VByName("link"),
|
||||
campaign=VPromoCampaign("campaign"),
|
||||
customer_id=VInt("customer_id", min=0),
|
||||
pay_id=VInt("account", min=0),
|
||||
edit=VBoolean("edit"),
|
||||
address=ValidAddress(
|
||||
["firstName", "lastName", "company", "address", "city", "state",
|
||||
"zip", "country", "phoneNumber"]
|
||||
),
|
||||
creditcard=ValidCard(["cardNumber", "expirationDate", "cardCode"]),
|
||||
)
|
||||
def POST_update_pay(self, form, jquery, link, campaign, customer_id, pay_id,
|
||||
edit, address, creditcard):
|
||||
if not g.authorizenetapi:
|
||||
@@ -1033,7 +1035,9 @@ class PromoteApiController(ApiController):
|
||||
|
||||
pay_id = edit_profile(c.user, address, creditcard, pay_id)
|
||||
|
||||
reason = None
|
||||
if pay_id:
|
||||
promote.new_payment_method(c.user, link)
|
||||
|
||||
if pay_id:
|
||||
success, reason = promote.auth_campaign(link, campaign, c.user,
|
||||
pay_id)
|
||||
@@ -1041,9 +1045,13 @@ class PromoteApiController(ApiController):
|
||||
if success:
|
||||
form.redirect(promote.promo_edit_url(link))
|
||||
return
|
||||
|
||||
msg = reason or _("failed to authenticate card. sorry.")
|
||||
form.set_text(".status", msg)
|
||||
else:
|
||||
promote.failed_payment_method(c.user, link)
|
||||
msg = reason or _("failed to authenticate card. sorry.")
|
||||
form.set_text(".status", msg)
|
||||
else:
|
||||
promote.failed_payment_method(c.user, link)
|
||||
form.set_text(".status", _("failed to authenticate card. sorry."))
|
||||
|
||||
@validate(VSponsor("link_name"),
|
||||
VModhash(),
|
||||
|
||||
@@ -257,6 +257,15 @@ def void_payment(thing, campaign, reason):
|
||||
reason=reason)
|
||||
|
||||
|
||||
def suspicious_payment(user, link):
|
||||
from r2.lib.pages import SuspiciousPaymentEmail
|
||||
|
||||
email = "fraud@reddit.com"
|
||||
body = SuspiciousPaymentEmail(user, link).render(style="email")
|
||||
kind = Email.Kind.SUSPICIOUS_PAYMENT
|
||||
_system_email(email, body, kind)
|
||||
|
||||
|
||||
def send_html_email(to_addr, from_addr, subject, html, subtype="html"):
|
||||
from r2.lib.filters import _force_utf8
|
||||
msg = MIMEText(_force_utf8(html), subtype)
|
||||
|
||||
@@ -2757,6 +2757,12 @@ class VerifyEmail(Templated):
|
||||
class Promo_Email(Templated):
|
||||
pass
|
||||
|
||||
|
||||
class SuspiciousPaymentEmail(Templated):
|
||||
def __init__(self, user, link):
|
||||
Templated.__init__(self, user=user, link=link)
|
||||
|
||||
|
||||
class ResetPassword(Templated):
|
||||
"""Form for actually resetting a lost password, after the user has
|
||||
clicked on the link provided to them in the Password_Reset email
|
||||
|
||||
@@ -905,6 +905,29 @@ def get_spent_amount(campaign):
|
||||
return spent
|
||||
|
||||
|
||||
PAYMENT_METHODS_ALERT_LIMIT = 3
|
||||
FAILED_PAYMENTS_ALERT_LIMIT = 5
|
||||
|
||||
def new_payment_method(user, link):
|
||||
user._incr('num_payment_methods')
|
||||
if (user.num_payment_methods > PAYMENT_METHODS_ALERT_LIMIT and
|
||||
not user.payment_flagged):
|
||||
payment_flag_user(user, link)
|
||||
|
||||
|
||||
def failed_payment_method(user, link):
|
||||
user._incr('num_failed_payments')
|
||||
if (user.num_failed_payments > FAILED_PAYMENTS_ALERT_LIMIT and
|
||||
not user.payment_flagged):
|
||||
payment_flag_user(user, link)
|
||||
|
||||
|
||||
def payment_flag_user(user, link):
|
||||
user.payment_flagged = True
|
||||
user._commit()
|
||||
emailer.suspicious_payment(user, link)
|
||||
|
||||
|
||||
def Run(verbose=True):
|
||||
"""reddit-job-update_promos: Intended to be run hourly to pull in
|
||||
scheduled changes to ads
|
||||
|
||||
@@ -62,6 +62,8 @@ class Account(Thing):
|
||||
'report_ignored', 'spammer',
|
||||
'reported', 'gold_creddits',
|
||||
'inbox_count',
|
||||
'num_payment_methods',
|
||||
'num_failed_payments',
|
||||
)
|
||||
_int_prop_suffix = '_karma'
|
||||
_essentials = ('name', )
|
||||
@@ -136,6 +138,7 @@ class Account(Thing):
|
||||
num_failed_payments=0,
|
||||
pref_show_snoovatar=False,
|
||||
gild_reveal_username=False,
|
||||
payment_flagged=False,
|
||||
)
|
||||
_preference_attrs = tuple(k for k in _defaults.keys()
|
||||
if k.startswith("pref_"))
|
||||
|
||||
@@ -306,6 +306,7 @@ class Email(object):
|
||||
"REFUNDED_PROMO",
|
||||
"VOID_PAYMENT",
|
||||
"GOLD_GIFT_CODE",
|
||||
"SUSPICIOUS_PAYMENT",
|
||||
)
|
||||
|
||||
# Do not remove anything from this dictionary! See above comment.
|
||||
@@ -331,6 +332,7 @@ class Email(object):
|
||||
Kind.REFUNDED_PROMO: _("[reddit] your campaign didn't get enough impressions"),
|
||||
Kind.VOID_PAYMENT: _("[reddit] your payment has been voided"),
|
||||
Kind.GOLD_GIFT_CODE: _("[reddit] your reddit gold gift code"),
|
||||
Kind.SUSPICIOUS_PAYMENT: _("[selfserve] suspicious payment alert"),
|
||||
}
|
||||
|
||||
def __init__(self, user, thing, email, from_name, date, ip,
|
||||
|
||||
31
r2/r2/templates/suspiciouspaymentemail.email
Normal file
31
r2/r2/templates/suspiciouspaymentemail.email
Normal file
@@ -0,0 +1,31 @@
|
||||
## The contents of this file are subject to the Common Public Attribution
|
||||
## License Version 1.0. (the "License"); you may not use this file except in
|
||||
## compliance with the License. You may obtain a copy of the License at
|
||||
## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
|
||||
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
|
||||
## software over a computer network and provide for limited attribution for the
|
||||
## Original Developer. In addition, Exhibit A has been modified to be
|
||||
## consistent with Exhibit B.
|
||||
##
|
||||
## Software distributed under the License is distributed on an "AS IS" basis,
|
||||
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
## the specific language governing rights and limitations under the License.
|
||||
##
|
||||
## The Original Code is reddit.
|
||||
##
|
||||
## The Original Developer is the Initial Developer. The Initial Developer of
|
||||
## the Original Code is reddit Inc.
|
||||
##
|
||||
## All portions of the code written by reddit are Copyright (c) 2006-2014
|
||||
## reddit Inc. All Rights Reserved.
|
||||
###############################################################################
|
||||
|
||||
<%!
|
||||
from r2.lib.promote import promo_edit_url
|
||||
%>
|
||||
|
||||
<%namespace file="utils.html" import="plain_link"/>
|
||||
|
||||
There is suspicious payment activity by ${plain_link("/u/%s" % thing.user.name, "/user/%s/promoted" % thing.user.name, _sr_path=False)}.
|
||||
|
||||
This report was triggered by the promotion ${plain_link(thing.link.title, promo_edit_url(thing.link), _sr_path=False)}.
|
||||
Reference in New Issue
Block a user