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
1111
1212
1313class AdminBaseHandler (BaseHandler ):
@@ -52,6 +52,62 @@ def get(self):
5252 return self .render ("admin/index.html" )
5353
5454
55+ class UserHandler (AdminBaseHandler ):
56+ @tornado .web .authenticated
57+ def get (self , user_name ):
58+ plan_names = {
59+ "mltshp-single-canceled" : "Single Scoop - Canceled" ,
60+ "mltshp-single" : "Single Scoop" ,
61+ "mltshp-double-canceled" : "Double Scoop - Canceled" ,
62+ "mltshp-double" : "Double Scoop" ,
63+ }
64+ user = User .get ('name=%s' , user_name )
65+ if not user :
66+ return self .redirect ('/admin?error=User%20not%20found' )
67+
68+ post_count = "{:,d}" .format (Sharedfile .where_count ("user_id=%s and deleted=0" , user .id ))
69+ shake_count = "{:,d}" .format (Shake .where_count ("user_id=%s and deleted=0" , user .id ))
70+ comment_count = "{:,d}" .format (Comment .where_count ("user_id=%s and deleted=0" , user .id ))
71+ like_count = "{:,d}" .format (Favorite .where_count ("user_id=%s and deleted=0" , user .id ))
72+ last_activity_date = user .get_last_activity_date ()
73+ pretty_last_activity_date = last_activity_date and pretty_date (last_activity_date ) or "None"
74+ subscribed = bool (user .is_paid )
75+ subscription = subscribed and user .active_paid_subscription ()
76+ subscription_level = plan_names .get (user .stripe_plan_id ) or None
77+ subscription_start = subscription and subscription ['start_date' ]
78+ subscription_end = subscription and subscription ['end_date' ]
79+ all_payments = PaymentLog .where ("user_id=%s" , user .id )
80+ total_payments = 0.00
81+ for payment in all_payments :
82+ if payment .status == "payment" :
83+ total_payments = total_payments + float (payment .transaction_amount .split (" " )[1 ])
84+ uploaded_all_time_mb = "{:,.2f}" .format (user .uploaded_kilobytes () / 1024 )
85+ uploaded_this_month_mb = "{:,.2f}" .format (user .uploaded_this_month () / 1024 )
86+ # select all _original_ posts from this user; we care less about reposts for this view
87+ recent_posts = Sharedfile .where ("user_id=%s and original_id=0 order by created_at desc limit 50" , user .id )
88+ recent_comments = Comment .where ("user_id=%s order by created_at desc limit 100" , user .id )
89+
90+ return self .render (
91+ "admin/user.html" ,
92+ user = user ,
93+ user_name = user_name ,
94+ post_count = post_count ,
95+ shake_count = shake_count ,
96+ comment_count = comment_count ,
97+ like_count = like_count ,
98+ uploaded_all_time_mb = uploaded_all_time_mb ,
99+ uploaded_this_month_mb = uploaded_this_month_mb ,
100+ total_payments = total_payments ,
101+ subscribed = subscribed ,
102+ subscription_level = subscription_level ,
103+ subscription_start = subscription_start ,
104+ subscription_end = subscription_end ,
105+ last_activity_date = last_activity_date ,
106+ pretty_last_activity_date = pretty_last_activity_date ,
107+ recent_posts = recent_posts ,
108+ recent_comments = recent_comments ,)
109+
110+
55111class NSFWUserHandler (AdminBaseHandler ):
56112 @tornado .web .authenticated
57113 def get (self ):
@@ -80,11 +136,17 @@ def get(self):
80136 if not self .admin_user .is_superuser ():
81137 return self .redirect ('/admin' )
82138
139+ share_key = self .get_argument ("share_key" , None )
140+ if share_key :
141+ sharedfile = Sharedfile .get ("share_key=%s AND deleted=0" , share_key )
142+ else :
143+ sharedfile = None
144+
83145 return self .render (
84146 "admin/image-takedown.html" ,
85- share_key = "" ,
147+ share_key = share_key or "" ,
86148 confirm_step = False ,
87- sharedfile = None ,
149+ sharedfile = sharedfile ,
88150 comment = "" ,
89151 canceled = self .get_argument ('canceled' , "0" ) == "1" ,
90152 deleted = self .get_argument ('deleted' , "0" ) == "1" )
@@ -168,19 +230,26 @@ def post(self):
168230
169231
170232class 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-
177233 @tornado .web .authenticated
178234 def post (self ):
179- user_id = self .get_argument ('user_id' )
235+ # Only a superuser can delete users
236+ if not self .admin_user .is_superuser ():
237+ return self .write ({'error' : 'not allowed' })
238+
180239 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 )
240+ user = None
241+ if user_name :
242+ user = User .get ('name=%s' , user_name )
243+
244+ if user :
245+ # admin users cannot be deleted (moderator or superuser)
246+ if user .is_admin ():
247+ return self .write ({'error' : 'cannot delete admin' })
248+
249+ user .delete ()
250+ return self .write ({'response' : 'ok' })
251+ else :
252+ return self .write ({'error' : 'user not found' })
184253
185254
186255class FlagNSFWHandler (AdminBaseHandler ):
@@ -190,6 +259,7 @@ def post(self, user_name):
190259 if not user :
191260 return self .redirect ('/' )
192261
262+ json = int (self .get_argument ("json" , 0 ))
193263 nsfw = int (self .get_argument ("nsfw" , 0 ))
194264 if nsfw == 1 :
195265 user .flag_nsfw ()
@@ -198,7 +268,10 @@ def post(self, user_name):
198268 user .save ()
199269 send_slack_notification ("%s flagged user '%s' as %s" % (self .admin_user .name , user .name , nsfw == 1 and "NSFW" or "SFW" ),
200270 channel = "#moderation" , icon_emoji = ":ghost:" , username = "modbot" )
201- return self .redirect ("/user/%s" % user .name )
271+ if json == 1 :
272+ return self .write ({'response' : 'ok' })
273+ else :
274+ return self .redirect ("/user/%s" % user .name )
202275
203276
204277class RecommendedGroupShakeHandler (AdminBaseHandler ):
0 commit comments