2022-11-15 09:19:08 +00:00
import sqlalchemy . exc
from files . classes import *
2022-05-04 23:09:46 +00:00
from files . helpers . alerts import *
2022-12-11 23:44:34 +00:00
from files . helpers . config . const import *
2022-11-15 09:19:08 +00:00
from files . helpers . get import *
from files . routes . wrappers import *
2022-05-04 23:09:46 +00:00
from files . __main__ import app , limiter
@app.get ( " /authorize " )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-05-04 23:09:46 +00:00
@auth_required
2023-07-30 00:42:06 +00:00
def authorize_prompt ( v ) :
2022-05-04 23:09:46 +00:00
client_id = request . values . get ( " client_id " )
2023-03-16 06:27:58 +00:00
application = g . db . query ( OauthApp ) . filter_by ( client_id = client_id ) . one_or_none ( )
2023-07-23 00:36:28 +00:00
if not application :
return { " oauth_error " : " Invalid `client_id` " } , 400
2022-05-04 23:09:46 +00:00
return render_template ( " oauth.html " , v = v , application = application )
@app.post ( " /authorize " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-05-04 23:09:46 +00:00
@auth_required
def authorize ( v ) :
client_id = request . values . get ( " client_id " )
2023-03-16 06:27:58 +00:00
application = g . db . query ( OauthApp ) . filter_by ( client_id = client_id ) . one_or_none ( )
2023-07-23 00:36:28 +00:00
if not application :
return { " oauth_error " : " Invalid `client_id` " } , 400
2022-05-04 23:09:46 +00:00
access_token = secrets . token_urlsafe ( 128 ) [ : 128 ]
2023-08-31 09:16:10 +00:00
new_auth = ClientAuth ( oauth_client = application . id , user_id = v . id , access_token = access_token )
g . db . add ( new_auth )
2022-05-04 23:09:46 +00:00
return redirect ( f " { application . redirect_uri } ?token= { access_token } " )
2022-12-29 10:39:10 +00:00
@app.post ( " /rescind/<int:aid> " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-07-15 00:12:54 +00:00
@auth_required
def rescind ( v , aid ) :
2023-03-16 06:27:58 +00:00
auth = g . db . query ( ClientAuth ) . filter_by ( oauth_client = aid , user_id = v . id ) . one_or_none ( )
2022-07-15 00:12:54 +00:00
if not auth : abort ( 400 )
2023-03-16 06:27:58 +00:00
g . db . delete ( auth )
2022-07-15 00:12:54 +00:00
return { " message " : " Authorization revoked! " }
2022-05-04 23:09:46 +00:00
@app.post ( " /api_keys " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-09-14 16:49:46 +00:00
@auth_required
2022-05-04 23:09:46 +00:00
def request_api_keys ( v ) :
2024-02-14 09:27:00 +00:00
description = request . values . get ( " description " , " " ) . strip ( )
if len ( description ) > 256 :
2024-02-14 09:34:49 +00:00
abort ( 400 , ' App description is too long (max 256 characters) ' )
2024-02-14 09:27:00 +00:00
2022-05-04 23:09:46 +00:00
new_app = OauthApp (
app_name = request . values . get ( ' name ' ) . replace ( ' < ' , ' ' ) . replace ( ' > ' , ' ' ) ,
redirect_uri = request . values . get ( ' redirect_uri ' ) ,
author_id = v . id ,
2024-02-14 09:27:00 +00:00
description = description ,
2022-05-04 23:09:46 +00:00
)
2023-03-16 06:27:58 +00:00
g . db . add ( new_app )
2022-05-04 23:09:46 +00:00
body = f " @ { v . username } has requested API keys for ` { request . values . get ( ' name ' ) } `. You can approve or deny the request [here](/admin/apps). "
2024-02-17 14:00:59 +00:00
send_repeatable_notification ( AEVANN_ID , body )
2022-05-04 23:09:46 +00:00
2023-08-11 21:50:23 +00:00
return { " message " : " API keys requested successfully! " }
2022-05-04 23:09:46 +00:00
2022-12-29 10:39:10 +00:00
@app.post ( " /delete_app/<int:aid> " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-05-04 23:09:46 +00:00
@auth_required
def delete_oauth_app ( v , aid ) :
2022-10-16 09:51:42 +00:00
try :
aid = int ( aid )
except :
abort ( 404 )
2023-03-16 06:27:58 +00:00
app = g . db . get ( OauthApp , aid )
2022-09-23 12:08:54 +00:00
if not app : abort ( 404 )
2023-01-01 11:36:20 +00:00
2022-05-04 23:09:46 +00:00
if app . author_id != v . id : abort ( 403 )
2023-08-05 19:26:42 +00:00
for auth in g . db . query ( ClientAuth ) . filter_by ( oauth_client = app . id ) :
2023-03-16 06:27:58 +00:00
g . db . delete ( auth )
2022-05-04 23:09:46 +00:00
2023-03-16 06:27:58 +00:00
g . db . delete ( app )
2022-05-04 23:09:46 +00:00
return redirect ( ' /apps ' )
2022-12-29 10:39:10 +00:00
@app.post ( " /edit_app/<int:aid> " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-09-14 16:49:46 +00:00
@auth_required
2022-05-04 23:09:46 +00:00
def edit_oauth_app ( v , aid ) :
2022-10-16 09:51:42 +00:00
try :
aid = int ( aid )
except :
abort ( 404 )
2023-03-16 06:27:58 +00:00
app = g . db . get ( OauthApp , aid )
2022-09-23 12:08:54 +00:00
if not app : abort ( 404 )
2022-05-04 23:09:46 +00:00
if app . author_id != v . id : abort ( 403 )
app . redirect_uri = request . values . get ( ' redirect_uri ' )
app . app_name = request . values . get ( ' name ' )
2024-02-14 09:27:00 +00:00
description = request . values . get ( " description " , " " ) . strip ( )
if len ( description ) > 256 :
2024-02-14 09:34:49 +00:00
abort ( 400 , ' App description is too long (max 256 characters) ' )
2024-02-14 09:27:00 +00:00
app . description = description
2022-05-04 23:09:46 +00:00
2023-03-16 06:27:58 +00:00
g . db . add ( app )
2022-05-04 23:09:46 +00:00
2023-08-11 21:50:23 +00:00
return { " message " : " App edited successfully! " }
2022-05-04 23:09:46 +00:00
2022-12-29 10:39:10 +00:00
@app.post ( " /admin/app/approve/<int:aid> " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-10-06 07:40:36 +00:00
@admin_level_required ( PERMS [ ' APPS_MODERATION ' ] )
2022-05-04 23:09:46 +00:00
def admin_app_approve ( v , aid ) :
2023-03-16 06:27:58 +00:00
app = g . db . get ( OauthApp , aid )
2022-09-23 12:08:54 +00:00
if not app : abort ( 404 )
2022-05-04 23:09:46 +00:00
user = app . author
2022-07-18 00:46:46 +00:00
if not app . client_id :
app . client_id = secrets . token_urlsafe ( 64 ) [ : 64 ]
2023-03-16 06:27:58 +00:00
g . db . add ( app )
2022-07-18 00:46:46 +00:00
access_token = secrets . token_urlsafe ( 128 ) [ : 128 ]
new_auth = ClientAuth (
oauth_client = app . id ,
user_id = user . id ,
access_token = access_token
)
2022-05-04 23:09:46 +00:00
2023-03-16 06:27:58 +00:00
g . db . add ( new_auth )
2022-05-04 23:09:46 +00:00
2024-02-18 16:10:24 +00:00
send_repeatable_notification ( user . id , f " @ { v . username } (a site admin) has approved your application ` { app . app_name } `. Here ' s your access token: || { access_token } || \n \n Please check the guide [here](/api) if you don ' t know what to do next! " )
2022-05-04 23:09:46 +00:00
2022-07-18 00:46:46 +00:00
ma = ModAction (
kind = " approve_app " ,
user_id = v . id ,
target_user_id = user . id ,
)
2023-03-16 06:27:58 +00:00
g . db . add ( ma )
2022-05-04 23:09:46 +00:00
2022-09-11 14:32:00 +00:00
return { " message " : f " ' { app . app_name } ' approved! " }
2022-05-04 23:09:46 +00:00
2022-12-29 10:39:10 +00:00
@app.post ( " /admin/app/revoke/<int:aid> " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-10-06 07:40:36 +00:00
@admin_level_required ( PERMS [ ' APPS_MODERATION ' ] )
2022-05-04 23:09:46 +00:00
def admin_app_revoke ( v , aid ) :
2023-03-16 06:27:58 +00:00
app = g . db . get ( OauthApp , aid )
2022-05-04 23:09:46 +00:00
if app :
2023-08-05 19:26:42 +00:00
for auth in g . db . query ( ClientAuth ) . filter_by ( oauth_client = app . id ) : g . db . delete ( auth )
2022-05-04 23:09:46 +00:00
2022-08-25 15:56:51 +00:00
if v . id != app . author . id :
2024-02-18 16:10:24 +00:00
send_repeatable_notification ( app . author . id , f " @ { v . username } (a site admin) has revoked your application ` { app . app_name } `. " )
2022-05-04 23:09:46 +00:00
2023-03-16 06:27:58 +00:00
g . db . delete ( app )
2022-05-04 23:09:46 +00:00
ma = ModAction (
kind = " revoke_app " ,
user_id = v . id ,
target_user_id = app . author . id ,
)
2023-03-16 06:27:58 +00:00
g . db . add ( ma )
2022-05-04 23:09:46 +00:00
2022-09-11 14:32:00 +00:00
return { " message " : f " ' { app . app_name } ' revoked! " }
2022-05-04 23:09:46 +00:00
2022-12-29 10:39:10 +00:00
@app.post ( " /admin/app/reject/<int:aid> " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-10-06 07:40:36 +00:00
@admin_level_required ( PERMS [ ' APPS_MODERATION ' ] )
2022-05-04 23:09:46 +00:00
def admin_app_reject ( v , aid ) :
2023-03-16 06:27:58 +00:00
app = g . db . get ( OauthApp , aid )
2022-05-04 23:09:46 +00:00
if app :
2023-08-05 19:26:42 +00:00
for auth in g . db . query ( ClientAuth ) . filter_by ( oauth_client = app . id ) : g . db . delete ( auth )
2022-05-04 23:09:46 +00:00
2022-09-12 17:52:07 +00:00
if v . id != app . author . id :
2024-02-18 16:10:24 +00:00
send_repeatable_notification ( app . author . id , f " @ { v . username } (a site admin) has rejected your application ` { app . app_name } `. " )
2022-05-04 23:09:46 +00:00
2023-03-16 06:27:58 +00:00
g . db . delete ( app )
2022-05-04 23:09:46 +00:00
ma = ModAction (
kind = " reject_app " ,
user_id = v . id ,
target_user_id = app . author . id ,
)
2023-03-16 06:27:58 +00:00
g . db . add ( ma )
2022-05-04 23:09:46 +00:00
2022-09-11 14:32:00 +00:00
return { " message " : f " ' { app . app_name } ' rejected! " }
2022-05-04 23:09:46 +00:00
2022-12-29 10:39:10 +00:00
@app.get ( " /admin/app/<int:aid>/posts " )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-10-06 07:40:36 +00:00
@admin_level_required ( PERMS [ ' APPS_MODERATION ' ] )
2022-10-28 20:13:58 +00:00
def admin_app_id_posts ( v , aid ) :
2023-03-16 06:27:58 +00:00
oauth = g . db . get ( OauthApp , aid )
2022-09-23 12:08:54 +00:00
if not oauth : abort ( 404 )
2022-05-04 23:09:46 +00:00
2023-05-05 05:23:59 +00:00
page = get_page ( )
2023-06-07 23:26:32 +00:00
pids , total = oauth . idlist ( Post , page = page )
2022-05-04 23:09:46 +00:00
2023-05-05 21:44:24 +00:00
posts = get_posts ( pids , v = v )
2022-05-04 23:09:46 +00:00
return render_template ( " admin/app.html " ,
2022-09-04 23:15:37 +00:00
v = v ,
app = oauth ,
listing = posts ,
2023-05-05 21:44:24 +00:00
total = total
2022-09-04 23:15:37 +00:00
)
2022-05-04 23:09:46 +00:00
2022-12-29 10:39:10 +00:00
@app.get ( " /admin/app/<int:aid>/comments " )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-10-06 07:40:36 +00:00
@admin_level_required ( PERMS [ ' APPS_MODERATION ' ] )
2022-05-04 23:09:46 +00:00
def admin_app_id_comments ( v , aid ) :
2023-03-16 06:27:58 +00:00
oauth = g . db . get ( OauthApp , aid )
2022-09-23 12:08:54 +00:00
if not oauth : abort ( 404 )
2022-05-04 23:09:46 +00:00
2023-05-05 05:23:59 +00:00
page = get_page ( )
2023-05-05 21:44:24 +00:00
cids , total = oauth . idlist ( Comment , page = page )
2022-05-04 23:09:46 +00:00
2023-05-05 21:44:24 +00:00
comments = get_comments ( cids , v = v )
2022-05-04 23:09:46 +00:00
return render_template ( " admin/app.html " ,
2022-09-04 23:15:37 +00:00
v = v ,
app = oauth ,
comments = comments ,
2023-05-05 21:44:24 +00:00
total = total ,
2022-09-04 23:15:37 +00:00
standalone = True
)
2022-05-04 23:09:46 +00:00
@app.get ( " /admin/apps " )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-10-06 07:40:36 +00:00
@admin_level_required ( PERMS [ ' APPS_MODERATION ' ] )
2022-05-04 23:09:46 +00:00
def admin_apps_list ( v ) :
2023-03-16 06:27:58 +00:00
not_approved = g . db . query ( OauthApp ) . filter ( OauthApp . client_id == None ) . order_by ( OauthApp . id . desc ( ) ) . all ( )
2023-02-28 17:13:38 +00:00
2023-03-16 06:27:58 +00:00
approved = g . db . query ( OauthApp ) . filter ( OauthApp . client_id != None ) . order_by ( OauthApp . id . desc ( ) ) . all ( )
2023-02-28 17:13:38 +00:00
apps = not_approved + approved
2022-05-04 23:09:46 +00:00
return render_template ( " admin/apps.html " , v = v , apps = apps )
2022-12-29 10:39:10 +00:00
@app.post ( " /reroll/<int:aid> " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2022-05-04 23:09:46 +00:00
@auth_required
def reroll_oauth_tokens ( aid , v ) :
aid = aid
2023-03-16 06:27:58 +00:00
a = g . db . get ( OauthApp , aid )
2022-09-23 12:08:54 +00:00
if not a : abort ( 404 )
2022-05-04 23:09:46 +00:00
if a . author_id != v . id : abort ( 403 )
a . client_id = secrets . token_urlsafe ( 64 ) [ : 64 ]
2023-03-16 06:27:58 +00:00
g . db . add ( a )
2022-05-04 23:09:46 +00:00
2022-09-11 14:32:00 +00:00
return { " message " : f " Client ID for ' { a . app_name } ' has been rerolled! " , " id " : a . client_id }