66
77from .base import BaseHandler
88from models import Sharedfile , User , Shake , Invitation , Waitlist , ShakeCategory , \
9- DmcaTakedown , Comment
10- from lib .utilities import send_slack_notification
9+ DmcaTakedown , Comment , Favorite , PaymentLog , Conversation
10+ from lib .utilities import send_slack_notification , pretty_date
11+ from tasks .admin import delete_account
1112
1213
1314class AdminBaseHandler (BaseHandler ):
@@ -52,6 +53,62 @@ def get(self):
5253 return self .render ("admin/index.html" )
5354
5455
56+ class UserHandler (AdminBaseHandler ):
57+ @tornado .web .authenticated
58+ def get (self , user_name ):
59+ plan_names = {
60+ "mltshp-single-canceled" : "Single Scoop - Canceled" ,
61+ "mltshp-single" : "Single Scoop" ,
62+ "mltshp-double-canceled" : "Double Scoop - Canceled" ,
63+ "mltshp-double" : "Double Scoop" ,
64+ }
65+ user = User .get ('name=%s' , user_name )
66+ if not user :
67+ return self .redirect ('/admin?error=User%20not%20found' )
68+
69+ post_count = "{:,d}" .format (Sharedfile .where_count ("user_id=%s and deleted=0" , user .id ))
70+ shake_count = "{:,d}" .format (Shake .where_count ("user_id=%s and deleted=0" , user .id ))
71+ comment_count = "{:,d}" .format (Comment .where_count ("user_id=%s and deleted=0" , user .id ))
72+ like_count = "{:,d}" .format (Favorite .where_count ("user_id=%s and deleted=0" , user .id ))
73+ last_activity_date = user .get_last_activity_date ()
74+ pretty_last_activity_date = last_activity_date and pretty_date (last_activity_date ) or "None"
75+ subscribed = bool (user .is_paid )
76+ subscription = subscribed and user .active_paid_subscription ()
77+ subscription_level = plan_names .get (user .stripe_plan_id ) or None
78+ subscription_start = subscription and subscription ['start_date' ]
79+ subscription_end = subscription and subscription ['end_date' ]
80+ all_payments = PaymentLog .where ("user_id=%s" , user .id )
81+ total_payments = 0.00
82+ for payment in all_payments :
83+ if payment .status == "payment" :
84+ total_payments = total_payments + float (payment .transaction_amount .split (" " )[1 ])
85+ uploaded_all_time_mb = "{:,.2f}" .format (user .uploaded_kilobytes () / 1024 )
86+ uploaded_this_month_mb = "{:,.2f}" .format (user .uploaded_this_month () / 1024 )
87+ # select all _original_ posts from this user; we care less about reposts for this view
88+ recent_posts = Sharedfile .where ("user_id=%s and original_id=0 order by created_at desc limit 50" , user .id )
89+ recent_comments = Comment .where ("user_id=%s order by created_at desc limit 100" , user .id )
90+
91+ return self .render (
92+ "admin/user.html" ,
93+ user = user ,
94+ user_name = user_name ,
95+ post_count = post_count ,
96+ shake_count = shake_count ,
97+ comment_count = comment_count ,
98+ like_count = like_count ,
99+ uploaded_all_time_mb = uploaded_all_time_mb ,
100+ uploaded_this_month_mb = uploaded_this_month_mb ,
101+ total_payments = total_payments ,
102+ subscribed = subscribed ,
103+ subscription_level = subscription_level ,
104+ subscription_start = subscription_start ,
105+ subscription_end = subscription_end ,
106+ last_activity_date = last_activity_date ,
107+ pretty_last_activity_date = pretty_last_activity_date ,
108+ recent_posts = recent_posts ,
109+ recent_comments = recent_comments ,)
110+
111+
55112class NSFWUserHandler (AdminBaseHandler ):
56113 @tornado .web .authenticated
57114 def get (self ):
@@ -80,11 +137,17 @@ def get(self):
80137 if not self .admin_user .is_superuser ():
81138 return self .redirect ('/admin' )
82139
140+ share_key = self .get_argument ("share_key" , None )
141+ if share_key :
142+ sharedfile = Sharedfile .get ("share_key=%s AND deleted=0" , share_key )
143+ else :
144+ sharedfile = None
145+
83146 return self .render (
84147 "admin/image-takedown.html" ,
85- share_key = "" ,
148+ share_key = share_key or "" ,
86149 confirm_step = False ,
87- sharedfile = None ,
150+ sharedfile = sharedfile ,
88151 comment = "" ,
89152 canceled = self .get_argument ('canceled' , "0" ) == "1" ,
90153 deleted = self .get_argument ('deleted' , "0" ) == "1" )
@@ -168,19 +231,30 @@ def post(self):
168231
169232
170233class DeleteUserHandler (AdminBaseHandler ):
171- @tornado .web .authenticated
172- def get (self ):
173- if not self .admin_user .is_superuser ():
174- return self .redirect ('/admin' )
175- return self .render ('admin/delete-user.html' )
176-
177234 @tornado .web .authenticated
178235 def post (self ):
179- user_id = self .get_argument ('user_id' )
236+ # Only a superuser can delete users
237+ if not self .admin_user .is_superuser ():
238+ return self .write ({'error' : 'not allowed' })
239+
180240 user_name = self .get_argument ('user_name' )
181- user = User .get ('name=%s and id=%s' , user_name , user_id )
182- user .delete ()
183- return self .redirect ('/user/%s' % user_name )
241+ user = None
242+ if user_name :
243+ user = User .get ('name=%s' , user_name )
244+
245+ if user :
246+ # admin users cannot be deleted (moderator or superuser)
247+ if user .is_admin ():
248+ return self .write ({'error' : 'cannot delete admin' })
249+
250+ # Flag as deleted; send full deletion work to the background
251+ user .deleted = 1
252+ user .save ()
253+
254+ delete_account .delay_or_run (user_id = user .id )
255+ return self .write ({'response' : 'ok' })
256+ else :
257+ return self .write ({'error' : 'user not found' })
184258
185259
186260class FlagNSFWHandler (AdminBaseHandler ):
@@ -190,6 +264,7 @@ def post(self, user_name):
190264 if not user :
191265 return self .redirect ('/' )
192266
267+ json = int (self .get_argument ("json" , 0 ))
193268 nsfw = int (self .get_argument ("nsfw" , 0 ))
194269 if nsfw == 1 :
195270 user .flag_nsfw ()
@@ -198,7 +273,10 @@ def post(self, user_name):
198273 user .save ()
199274 send_slack_notification ("%s flagged user '%s' as %s" % (self .admin_user .name , user .name , nsfw == 1 and "NSFW" or "SFW" ),
200275 channel = "#moderation" , icon_emoji = ":ghost:" , username = "modbot" )
201- return self .redirect ("/user/%s" % user .name )
276+ if json == 1 :
277+ return self .write ({'response' : 'ok' })
278+ else :
279+ return self .redirect ("/user/%s" % user .name )
202280
203281
204282class RecommendedGroupShakeHandler (AdminBaseHandler ):
0 commit comments