2022-07-29 22:07:08 +00:00
import time
2022-11-20 17:00:05 +00:00
import secrets
2022-05-04 23:09:46 +00:00
2022-11-15 09:19:08 +00:00
import user_agents
from flask import g , request , session
from files . classes . clients import ClientAuth
from files . helpers . alerts import *
from files . helpers . const import *
from files . helpers . get import get_account
from files . helpers . settings import get_setting
from files . routes . routehelpers import validate_formkey
from files . __main__ import app , cache , db_session , limiter
2022-11-22 23:37:55 +00:00
def session_init ( ) :
if not session . get ( " session_id " ) :
session . permanent = True
session [ " session_id " ] = secrets . token_hex ( 49 )
2022-10-15 07:31:24 +00:00
def calc_users ( v ) :
2022-11-26 02:21:38 +00:00
# temp logging code
if not hasattr ( g , ' is_api_or_xhr ' ) :
print ( " calc_users called with missing context data " )
if request :
print ( f " while serving { request . method } { request . full_path } " )
2022-11-26 02:22:55 +00:00
print ( f " user agent: { getattr ( g , ' agent ' , ' -attribute not present- ' ) } " )
2022-11-26 02:57:10 +00:00
print ( f " xhr? { request . headers . get ( ' xhr ' ) } / API client? { bool ( request . headers . get ( ' Authorization ' ) ) } " )
2022-11-26 02:21:38 +00:00
else :
print ( " no request context " )
print ( f " v: { v } " )
2022-11-26 02:57:10 +00:00
print ( f " db?: { hasattr ( g , ' db ' ) } " )
abort ( 500 , " hi!! it ' s @justcool393! If you get this could you PM me and tell me how you got this? i ' m trying to figure something out and if you can help I ' ll really appreciate it <3 " )
2022-11-26 02:21:38 +00:00
# end temp logging code
2022-10-15 07:31:24 +00:00
loggedin = cache . get ( f ' { SITE } _loggedin ' ) or { }
loggedout = cache . get ( f ' { SITE } _loggedout ' ) or { }
timestamp = int ( time . time ( ) )
2022-11-20 19:05:32 +00:00
2022-11-22 23:37:55 +00:00
session_init ( )
2022-10-15 07:31:24 +00:00
if v :
if session [ " session_id " ] in loggedout : del loggedout [ session [ " session_id " ] ]
loggedin [ v . id ] = timestamp
else :
ua = str ( user_agents . parse ( g . agent ) )
if ' spider ' not in ua . lower ( ) and ' bot ' not in ua . lower ( ) :
loggedout [ session [ " session_id " ] ] = ( timestamp , ua )
loggedin = { k : v for k , v in loggedin . items ( ) if ( timestamp - v ) < LOGGEDIN_ACTIVE_TIME }
loggedout = { k : v for k , v in loggedout . items ( ) if ( timestamp - v [ 0 ] ) < LOGGEDIN_ACTIVE_TIME }
cache . set ( f ' { SITE } _loggedin ' , loggedin )
cache . set ( f ' { SITE } _loggedout ' , loggedout )
g . loggedin_counter = len ( loggedin )
g . loggedout_counter = len ( loggedout )
2022-10-15 07:33:58 +00:00
return ' '
2022-10-15 07:31:24 +00:00
2022-05-04 23:09:46 +00:00
def get_logged_in_user ( ) :
2022-05-26 00:54:05 +00:00
if hasattr ( g , ' v ' ) : return g . v
2022-11-15 09:19:08 +00:00
if not getattr ( g , ' db ' , None ) : g . db = db_session ( )
2022-11-09 05:35:24 +00:00
g . desires_auth = True
2022-05-04 23:09:46 +00:00
v = None
token = request . headers . get ( " Authorization " , " " ) . strip ( )
if token :
client = g . db . query ( ClientAuth ) . filter ( ClientAuth . access_token == token ) . one_or_none ( )
if client :
v = client . user
v . client = client
else :
lo_user = session . get ( " lo_user " )
if lo_user :
id = int ( lo_user )
2022-09-05 20:37:38 +00:00
v = get_account ( id , graceful = True )
if not v :
session . clear ( )
return None
else :
2022-05-04 23:09:46 +00:00
nonce = session . get ( " login_nonce " , 0 )
2022-10-29 01:07:39 +00:00
if nonce < v . login_nonce or v . id != id :
session . clear ( )
return None
2022-05-04 23:09:46 +00:00
if request . method != " GET " :
submitted_key = request . values . get ( " formkey " )
2022-11-15 09:19:08 +00:00
if not validate_formkey ( v , submitted_key ) : abort ( 401 )
2022-05-04 23:09:46 +00:00
v . client = None
2022-10-15 09:11:36 +00:00
g . is_api_or_xhr = bool ( ( v and v . client ) or request . headers . get ( " xhr " ) )
2022-05-04 23:09:46 +00:00
2022-11-15 09:19:08 +00:00
if request . method . lower ( ) != " get " and get_setting ( ' Read-only mode ' ) and not ( v and v . admin_level > = PERMS [ ' SITE_BYPASS_READ_ONLY_MODE ' ] ) :
2022-05-04 23:09:46 +00:00
abort ( 403 )
2022-05-26 00:54:05 +00:00
g . v = v
2022-05-25 18:59:24 +00:00
2022-10-15 10:08:14 +00:00
if v :
v . poor = session . get ( ' poor ' )
# Check against last_active + ACTIVE_TIME to reduce frequency of
# UPDATEs in exchange for a ±ACTIVE_TIME margin of error.
timestamp = int ( time . time ( ) )
if ( v . last_active + LOGGEDIN_ACTIVE_TIME ) < timestamp :
v . last_active = timestamp
g . db . add ( v )
2022-06-27 03:46:32 +00:00
2022-09-13 07:23:23 +00:00
if AEVANN_ID and request . headers . get ( " Cf-Ipcountry " ) == ' EG ' :
2022-11-07 07:03:58 +00:00
if v and not v . username . startswith ( ' Aev ' ) and v . truescore > 0 :
2022-11-17 16:00:49 +00:00
with open ( " /eg " , " r+ " , encoding = " utf-8 " ) as f :
2022-09-13 07:23:23 +00:00
ip = request . headers . get ( ' CF-Connecting-IP ' )
if f ' @ { v . username } , ' not in f . read ( ) :
t = str ( time . strftime ( " %d / % B/ % Y % H: % M: % S UTC " , time . gmtime ( time . time ( ) ) ) )
2022-11-07 07:03:58 +00:00
f . write ( f ' @ { v . username } , { v . truescore } , { ip } , { t } \n ' )
2022-05-04 23:09:46 +00:00
return v
def auth_desired ( f ) :
def wrapper ( * args , * * kwargs ) :
2022-10-11 13:19:55 +00:00
v = get_logged_in_user ( )
2022-05-04 23:09:46 +00:00
return make_response ( f ( * args , v = v , * * kwargs ) )
wrapper . __name__ = f . __name__
return wrapper
2022-08-05 20:40:48 +00:00
def auth_desired_with_logingate ( f ) :
def wrapper ( * args , * * kwargs ) :
2022-10-11 13:19:55 +00:00
v = get_logged_in_user ( )
2022-11-15 09:19:08 +00:00
if get_setting ( ' login_required ' ) and not v : abort ( 401 )
2022-05-04 23:09:46 +00:00
2022-11-09 05:35:24 +00:00
if request . path . startswith ( ' /logged_out ' ) :
2022-09-20 00:51:01 +00:00
redir = request . full_path . replace ( ' /logged_out ' , ' ' )
if not redir : redir = ' / '
return redirect ( redir )
2022-08-05 20:40:48 +00:00
return make_response ( f ( * args , v = v , * * kwargs ) )
wrapper . __name__ = f . __name__
return wrapper
def auth_required ( f ) :
2022-05-04 23:09:46 +00:00
def wrapper ( * args , * * kwargs ) :
2022-10-11 13:19:55 +00:00
v = get_logged_in_user ( )
2022-05-04 23:09:46 +00:00
if not v : abort ( 401 )
return make_response ( f ( * args , v = v , * * kwargs ) )
wrapper . __name__ = f . __name__
return wrapper
def is_not_permabanned ( f ) :
def wrapper ( * args , * * kwargs ) :
2022-10-11 13:19:55 +00:00
v = get_logged_in_user ( )
2022-05-04 23:09:46 +00:00
if not v : abort ( 401 )
2022-10-11 06:15:09 +00:00
if v . is_suspended_permanently : abort ( 403 )
2022-05-04 23:09:46 +00:00
return make_response ( f ( * args , v = v , * * kwargs ) )
wrapper . __name__ = f . __name__
return wrapper
def admin_level_required ( x ) :
def wrapper_maker ( f ) :
def wrapper ( * args , * * kwargs ) :
2022-10-11 13:19:55 +00:00
v = get_logged_in_user ( )
2022-05-04 23:09:46 +00:00
if not v : abort ( 401 )
if v . admin_level < x : abort ( 403 )
2022-10-11 13:43:57 +00:00
return make_response ( f ( * args , v = v , * * kwargs ) )
2022-05-04 23:09:46 +00:00
wrapper . __name__ = f . __name__
return wrapper
2022-05-30 01:43:16 +00:00
return wrapper_maker
2022-10-11 07:17:54 +00:00
def feature_required ( x ) :
def wrapper_maker ( f ) :
def wrapper ( * args , * * kwargs ) :
if not FEATURES [ x ] : abort ( 404 )
2022-10-11 13:19:55 +00:00
return make_response ( f ( * args , * * kwargs ) )
2022-10-11 07:17:54 +00:00
wrapper . __name__ = f . __name__
return wrapper
2022-10-11 07:29:24 +00:00
return wrapper_maker
2022-11-13 06:07:15 +00:00
2022-11-13 08:36:36 +00:00
def ratelimit_user ( limit : Union [ str , Callable [ [ ] , str ] ] = DEFAULT_RATELIMIT_USER ) :
'''
Ratelimits based on a user . This requires at least auth_required ( or stronger ) to be present ,
otherwise logged out users will receive 500 s
'''
2022-11-13 12:24:58 +00:00
def inner ( func ) :
@functools.wraps ( func )
@limiter.limit ( limit , key_func = lambda : f ' { SITE } - { g . v . id } ' )
def wrapped ( * args , * * kwargs ) :
return func ( * args , * * kwargs )
return wrapped
return inner