2023-08-10 11:27:31 -04:00
from datetime import timedelta
2022-05-07 17:00:52 -04:00
from urllib . parse import quote
2023-08-10 11:27:31 -04:00
2022-05-07 17:00:52 -04:00
import django_rq
2023-07-04 17:21:17 -04:00
from django import forms
2023-08-10 11:27:31 -04:00
from django . conf import settings
from django . contrib import auth , messages
from django . contrib . auth import authenticate
from django . contrib . auth . decorators import login_required
from django . core . cache import cache
from django . core . exceptions import BadRequest , ObjectDoesNotExist
2023-07-04 17:21:17 -04:00
from django . core . mail import send_mail
2023-08-10 11:27:31 -04:00
from django . core . signing import TimestampSigner
2023-07-04 17:21:17 -04:00
from django . core . validators import EmailValidator
2023-08-10 11:27:31 -04:00
from django . db . models import Count , Q
from django . shortcuts import get_object_or_404 , redirect , render
from django . urls import reverse
from django . utils import timezone
2024-04-12 20:42:36 -04:00
from django . utils . baseconv import base62
2023-08-10 11:27:31 -04:00
from django . utils . translation import gettext_lazy as _
2023-12-25 17:27:31 -05:00
from django . views . decorators . http import require_http_methods
2023-08-10 11:27:31 -04:00
from loguru import logger
from common . config import *
2023-08-13 23:11:12 -04:00
from common . utils import AuthedHttpRequest
2023-08-10 11:27:31 -04:00
from journal . models import remove_data_by_user
from mastodon import mastodon_request_included
from mastodon . api import *
from mastodon . api import verify_account
2023-09-03 20:11:46 +00:00
from takahe . utils import Takahe
2023-08-10 11:27:31 -04:00
from . models import Preference , User
from . tasks import *
2022-05-07 17:00:52 -04:00
# the 'login' page that user can see
2024-04-23 23:57:49 -04:00
require_http_methods ( [ " GET " ] )
2022-05-07 17:00:52 -04:00
def login ( request ) :
2024-04-23 23:57:49 -04:00
selected_site = request . GET . get ( " site " , default = " " )
2022-05-07 17:00:52 -04:00
2024-04-23 23:57:49 -04:00
cache_key = " login_sites "
sites = cache . get ( cache_key , [ ] )
if not sites :
sites = list (
User . objects . filter ( is_active = True )
. values ( " mastodon_site " )
. annotate ( total = Count ( " mastodon_site " ) )
. order_by ( " -total " )
. values_list ( " mastodon_site " , flat = True )
2022-05-07 17:00:52 -04:00
)
2024-04-23 23:57:49 -04:00
cache . set ( cache_key , sites , timeout = 3600 * 8 )
# store redirect url in the cookie
if request . GET . get ( " next " ) :
request . session [ " next_url " ] = request . GET . get ( " next " )
invite_status = - 1 if settings . INVITE_ONLY else 0
if settings . INVITE_ONLY and request . GET . get ( " invite " ) :
if Takahe . verify_invite ( request . GET . get ( " invite " ) ) :
invite_status = 1
request . session [ " invite " ] = request . GET . get ( " invite " )
else :
invite_status = - 2
return render (
request ,
" users/login.html " ,
{
" sites " : sites ,
" scope " : quote ( settings . MASTODON_CLIENT_SCOPE ) ,
" selected_site " : selected_site ,
" allow_any_site " : settings . MASTODON_ALLOW_ANY_SITE ,
" invite_status " : invite_status ,
} ,
)
2022-05-07 17:00:52 -04:00
2023-07-04 17:21:17 -04:00
# connect will send verification email or redirect to mastodon server
2022-05-07 17:00:52 -04:00
def connect ( request ) :
2023-07-04 17:21:17 -04:00
if request . method == " POST " and request . POST . get ( " method " ) == " email " :
login_email = request . POST . get ( " email " , " " )
try :
EmailValidator ( ) ( login_email )
2024-04-06 00:13:50 -04:00
except Exception :
2023-07-04 17:21:17 -04:00
return render (
request ,
" common/error.html " ,
2024-05-19 16:32:59 -04:00
{ " msg " : _ ( " Invalid email address " ) } ,
2023-07-04 17:21:17 -04:00
)
2023-07-08 00:44:22 -04:00
user = User . objects . filter ( email__iexact = login_email ) . first ( )
2024-04-12 20:42:36 -04:00
code = base62 . encode ( random . randint ( pow ( 62 , 4 ) , pow ( 62 , 5 ) - 1 ) )
cache . set ( f " login_ { code } " , login_email , timeout = 60 * 15 )
request . session [ " login_email " ] = login_email
action = " login " if user else " register "
2023-07-04 17:21:17 -04:00
django_rq . get_queue ( " mastodon " ) . enqueue (
send_verification_link ,
user . pk if user else 0 ,
2024-04-12 20:42:36 -04:00
action ,
2023-07-04 17:21:17 -04:00
login_email ,
2024-04-12 20:42:36 -04:00
code ,
2023-07-04 17:21:17 -04:00
)
return render (
request ,
2024-04-12 20:42:36 -04:00
" common/verify.html " ,
2023-07-04 17:21:17 -04:00
{
2024-05-19 16:32:59 -04:00
" msg " : _ ( " Verification " ) ,
" secondary_msg " : _ (
" Verification email is being sent, please check your inbox. "
) ,
2024-04-12 20:42:36 -04:00
" action " : action ,
2023-07-04 17:21:17 -04:00
} ,
)
2023-01-01 23:50:57 -05:00
login_domain = (
request . session [ " swap_domain " ]
if request . session . get ( " swap_login " )
2023-07-04 17:21:17 -04:00
else ( request . POST . get ( " domain " ) or request . GET . get ( " domain " ) )
2023-01-01 23:50:57 -05:00
)
2022-05-07 17:00:52 -04:00
if not login_domain :
2023-01-01 23:50:57 -05:00
return render (
request ,
" common/error.html " ,
{
2024-05-19 16:32:59 -04:00
" msg " : _ ( " Missing instance domain " ) ,
2023-01-01 23:50:57 -05:00
" secondary_msg " : " " ,
} ,
)
login_domain = (
login_domain . strip ( ) . lower ( ) . split ( " // " ) [ - 1 ] . split ( " / " ) [ 0 ] . split ( " @ " ) [ - 1 ]
)
2023-02-14 17:19:00 -05:00
try :
2023-11-02 21:28:11 +01:00
app = get_or_create_fediverse_application ( login_domain )
2023-02-14 17:19:00 -05:00
if app . api_domain and app . api_domain != app . domain_name :
login_domain = app . api_domain
login_url = get_mastodon_login_url ( app , login_domain , request )
2023-12-25 22:38:09 -05:00
request . session [ " mastodon_domain " ] = app . domain_name
2023-02-14 17:19:00 -05:00
resp = redirect ( login_url )
resp . set_cookie ( " mastodon_domain " , app . domain_name )
return resp
except Exception as e :
2023-01-01 23:50:57 -05:00
return render (
request ,
" common/error.html " ,
{
2024-05-19 16:32:59 -04:00
" msg " : _ ( " Error connecting to instance " ) ,
" secondary_msg " : f " { login_domain } { e } " ,
2023-01-01 23:50:57 -05:00
} ,
)
2022-05-07 17:00:52 -04:00
# mastodon server redirect back to here
2023-12-25 17:27:31 -05:00
@require_http_methods ( [ " GET " ] )
2022-05-07 17:00:52 -04:00
@mastodon_request_included
2023-12-25 22:38:09 -05:00
def connect_redirect_back ( request ) :
2023-01-01 23:50:57 -05:00
code = request . GET . get ( " code " )
2023-01-10 16:52:00 -05:00
if not code :
return render (
request ,
" common/error.html " ,
2024-05-19 16:32:59 -04:00
{
" msg " : _ ( " Authentication failed " ) ,
" secondary_msg " : _ ( " Invalid response from Mastodon instance. " ) ,
} ,
2023-01-10 16:52:00 -05:00
)
2023-12-25 22:38:09 -05:00
site = request . session . get ( " mastodon_domain " )
2023-06-30 23:53:53 -04:00
if not site :
2023-01-10 16:52:00 -05:00
return render (
request ,
" common/error.html " ,
2024-05-19 16:32:59 -04:00
{
" msg " : _ ( " Authentication failed " ) ,
" secondary_msg " : _ ( " Invalid cookie data. " ) ,
} ,
2023-01-10 16:52:00 -05:00
)
2022-05-07 17:00:52 -04:00
try :
token , refresh_token = obtain_token ( site , request , code )
except ObjectDoesNotExist :
2024-04-23 23:57:49 -04:00
raise BadRequest ( _ ( " Invalid instance domain " ) )
2022-05-07 17:00:52 -04:00
if not token :
2023-01-10 16:52:00 -05:00
return render (
request ,
" common/error.html " ,
2024-05-19 16:32:59 -04:00
{
" msg " : _ ( " Authentication failed " ) ,
" secondary_msg " : _ ( " Invalid token from Mastodon instance. " ) ,
} ,
2023-01-10 16:52:00 -05:00
)
2022-05-07 17:00:52 -04:00
2023-01-01 23:50:57 -05:00
if (
request . session . get ( " swap_login " , False ) and request . user . is_authenticated
) : # swap login for existing user
2022-05-07 17:00:52 -04:00
return swap_login ( request , token , site , refresh_token )
2023-08-13 23:11:12 -04:00
user : User = authenticate ( request , token = token , site = site ) # type: ignore
2022-05-07 17:00:52 -04:00
if user : # existing user
2023-12-05 23:14:29 -05:00
user . mastodon_token = token
user . mastodon_refresh_token = refresh_token
2023-01-01 23:50:57 -05:00
user . save ( update_fields = [ " mastodon_token " , " mastodon_refresh_token " ] )
2023-08-13 23:11:12 -04:00
return login_existing_user ( request , user )
2022-05-07 17:00:52 -04:00
else : # newly registered user
code , user_data = verify_account ( site , token )
if code != 200 or user_data is None :
2024-05-19 16:32:59 -04:00
return render (
request ,
" common/error.html " ,
{
" msg " : _ ( " Authentication failed " ) ,
" secondary_msg " : _ ( " Invalid account data from Mastodon instance. " ) ,
} ,
)
2023-07-04 17:21:17 -04:00
return register_new_user (
request ,
2023-07-05 00:47:54 -04:00
username = None
if settings . MASTODON_ALLOW_ANY_SITE
else user_data [ " username " ] ,
2023-06-30 23:53:53 -04:00
mastodon_username = user_data [ " username " ] ,
2023-01-01 23:50:57 -05:00
mastodon_id = user_data [ " id " ] ,
2022-05-07 17:00:52 -04:00
mastodon_site = site ,
mastodon_token = token ,
mastodon_refresh_token = refresh_token ,
mastodon_account = user_data ,
)
2023-07-04 17:21:17 -04:00
def register_new_user ( request , * * param ) :
2023-09-03 20:11:46 +00:00
if settings . INVITE_ONLY :
if not Takahe . verify_invite ( request . session . get ( " invite " ) ) :
return render (
request ,
" common/error.html " ,
{
2024-05-19 16:32:59 -04:00
" msg " : _ ( " Authentication failed " ) ,
" secondary_msg " : _ ( " Registration is for invitation only " ) ,
2023-09-03 20:11:46 +00:00
} ,
)
else :
del request . session [ " invite " ]
2023-08-10 11:27:31 -04:00
new_user = User . register ( * * param )
2023-07-04 17:21:17 -04:00
request . session [ " new_user " ] = True
auth_login ( request , new_user )
2023-12-10 19:13:45 -05:00
response = redirect ( reverse ( " users:register " ) )
response . delete_cookie ( settings . TAKAHE_SESSION_COOKIE_NAME )
return response
2022-05-07 17:00:52 -04:00
2023-08-13 23:11:12 -04:00
def login_existing_user ( request , existing_user ) :
auth_login ( request , existing_user )
if not existing_user . username or not existing_user . identity :
2023-12-06 00:11:48 -05:00
response = redirect ( reverse ( " users:register " ) )
2023-08-13 23:11:12 -04:00
elif request . session . get ( " next_url " ) is not None :
response = redirect ( request . session . get ( " next_url " ) )
del request . session [ " next_url " ]
else :
response = redirect ( reverse ( " common:home " ) )
2023-12-10 19:13:45 -05:00
response . delete_cookie ( settings . TAKAHE_SESSION_COOKIE_NAME )
2023-08-13 23:11:12 -04:00
return response
2022-05-07 17:00:52 -04:00
@mastodon_request_included
@login_required
def logout ( request ) :
2024-04-23 23:57:49 -04:00
# revoke_token(request.user.mastodon_site, request.user.mastodon_token)
return auth_logout ( request )
2022-05-07 17:00:52 -04:00
@mastodon_request_included
@login_required
2024-04-23 23:57:49 -04:00
@require_http_methods ( [ " POST " ] )
2022-05-07 17:00:52 -04:00
def reconnect ( request ) :
2023-06-28 08:11:36 -04:00
if request . META . get ( " HTTP_AUTHORIZATION " ) :
raise BadRequest ( " Only for web login " )
2024-04-23 23:57:49 -04:00
request . session [ " swap_login " ] = True
request . session [ " swap_domain " ] = request . POST [ " domain " ]
return connect ( request )
2022-05-07 17:00:52 -04:00
2023-07-04 17:21:17 -04:00
class RegistrationForm ( forms . ModelForm ) :
email = forms . EmailField ( required = False )
class Meta :
model = User
fields = [ " username " ]
def clean_username ( self ) :
username = self . cleaned_data . get ( " username " )
if username and self . instance and self . instance . username :
username = self . instance . username
2023-07-08 00:44:22 -04:00
elif (
username
and User . objects . filter ( username__iexact = username )
. exclude ( pk = self . instance . pk if self . instance else - 1 )
. exists ( )
) :
raise forms . ValidationError ( _ ( " This username is already in use. " ) )
2023-07-04 17:21:17 -04:00
return username
def clean_email ( self ) :
email = self . cleaned_data . get ( " email " )
if (
email
2023-07-08 00:44:22 -04:00
and User . objects . filter ( email__iexact = email )
2023-07-04 17:21:17 -04:00
. exclude ( pk = self . instance . pk if self . instance else - 1 )
. exists ( )
) :
raise forms . ValidationError ( _ ( " This email address is already in use. " ) )
return email
2024-04-12 20:42:36 -04:00
def send_verification_link ( user_id , action , email , code = " " ) :
2023-07-04 17:21:17 -04:00
s = { " i " : user_id , " e " : email , " a " : action }
2023-12-05 23:14:29 -05:00
v = TimestampSigner ( ) . sign_object ( s )
2024-05-19 16:32:59 -04:00
footer = _ (
" \n \n If you did not mean to register or login, please ignore this email. If you are concerned with your account security, please change the email linked with your account, or contact us. "
)
site = settings . SITE_INFO [ " site_name " ]
2023-07-04 17:21:17 -04:00
if action == " verify " :
2024-05-19 16:32:59 -04:00
subject = f ' { site } - { _ ( " Verification " ) } '
2023-07-04 17:21:17 -04:00
url = settings . SITE_INFO [ " site_url " ] + " /account/verify_email?c= " + v
2024-05-19 16:32:59 -04:00
msg = _ ( " Click this link to verify your email address {email} \n {url} " ) . format (
email = email , url = url , code = code
)
msg + = footer
2023-07-04 17:21:17 -04:00
elif action == " login " :
2024-05-19 16:32:59 -04:00
subject = f ' { site } - { _ ( " Login " ) } { code } '
2023-07-04 17:21:17 -04:00
url = settings . SITE_INFO [ " site_url " ] + " /account/login/email?c= " + v
2024-05-19 16:32:59 -04:00
msg = _ (
" Use this code to confirm login as {email} \n \n {code} \n \n Or click this link to login \n {url} "
) . format ( email = email , url = url , code = code )
msg + = footer
2023-07-04 17:21:17 -04:00
elif action == " register " :
2024-05-19 16:32:59 -04:00
subject = f ' { site } - { _ ( " Register " ) } '
2023-07-04 17:21:17 -04:00
url = settings . SITE_INFO [ " site_url " ] + " /account/register_email?c= " + v
2024-05-19 16:32:59 -04:00
msg = _ (
" There is no account registered with this email address yet. {email} \n \n If you already have an account with a Fediverse identity, just login and add this email to you account. \n \n "
) . format ( email = email , url = url , code = code )
2023-07-04 17:21:17 -04:00
if settings . ALLOW_EMAIL_ONLY_ACCOUNT :
2024-05-19 16:32:59 -04:00
msg + = _ (
" \n If you prefer to register a new account, please use this code: {code} \n Or click this link: \n {url} "
) . format ( email = email , url = url , code = code )
msg + = footer
2022-05-07 17:00:52 -04:00
else :
2023-07-04 17:21:17 -04:00
raise ValueError ( " Invalid action " )
try :
2023-07-05 00:47:54 -04:00
logger . info ( f " Sending email to { email } with subject { subject } " )
2023-10-30 00:59:54 -04:00
logger . debug ( msg )
2023-07-04 17:21:17 -04:00
send_mail (
subject = subject ,
message = msg ,
from_email = settings . DEFAULT_FROM_EMAIL ,
recipient_list = [ email ] ,
fail_silently = False ,
)
except Exception as e :
logger . error ( e )
2024-04-12 20:42:36 -04:00
@require_http_methods ( [ " POST " ] )
def verify_code ( request ) :
code = request . POST . get ( " code " )
if not code :
return render (
request ,
" common/verify.html " ,
{
2024-05-19 16:32:59 -04:00
" error " : _ ( " Invalid verification code " ) ,
2024-04-12 20:42:36 -04:00
} ,
)
login_email = cache . get ( f " login_ { code } " )
if not login_email or request . session . get ( " login_email " ) != login_email :
return render (
request ,
" common/verify.html " ,
{
2024-05-19 16:32:59 -04:00
" error " : _ ( " Invalid verification code " ) ,
2024-04-12 20:42:36 -04:00
} ,
)
cache . delete ( f " login_ { code } " )
user = User . objects . filter ( email__iexact = login_email ) . first ( )
if user :
resp = login_existing_user ( request , user )
else :
resp = register_new_user ( request , username = None , email = login_email )
resp . set_cookie ( " mastodon_domain " , " @ " )
return resp
2023-07-04 17:21:17 -04:00
def verify_email ( request ) :
error = " "
try :
2023-12-05 23:14:29 -05:00
s = TimestampSigner ( ) . unsign_object ( request . GET . get ( " c " ) , max_age = 60 * 15 )
2023-07-05 00:47:54 -04:00
except Exception as e :
2023-12-09 16:25:41 -05:00
logger . warning ( f " login link invalid { e } " )
2024-05-19 16:32:59 -04:00
error = _ ( " Invalid verification link " )
2023-07-05 00:47:54 -04:00
return render (
request , " users/verify_email.html " , { " success " : False , " error " : error }
)
try :
2023-07-04 17:21:17 -04:00
email = s [ " e " ]
action = s [ " a " ]
if action == " verify " :
user = User . objects . get ( pk = s [ " i " ] )
if user . pending_email == email :
user . email = user . pending_email
user . pending_email = None
user . save ( update_fields = [ " email " , " pending_email " ] )
return render (
request , " users/verify_email.html " , { " success " : True , " user " : user }
)
else :
2024-05-19 16:32:59 -04:00
error = _ ( " Email mismatch " )
2023-07-04 17:21:17 -04:00
elif action == " login " :
user = User . objects . get ( pk = s [ " i " ] )
if user . email == email :
2023-08-13 23:11:12 -04:00
return login_existing_user ( request , user )
2023-07-04 17:21:17 -04:00
else :
2024-05-19 16:32:59 -04:00
error = _ ( " Email mismatch " )
2023-07-04 17:21:17 -04:00
elif action == " register " :
2023-07-08 00:44:22 -04:00
user = User . objects . filter ( email__iexact = email ) . first ( )
2023-07-04 17:21:17 -04:00
if user :
2024-05-19 16:32:59 -04:00
error = _ ( " Email in use " )
2023-07-04 17:21:17 -04:00
else :
return register_new_user ( request , username = None , email = email )
except Exception as e :
2023-07-05 00:47:54 -04:00
logger . error ( e )
2024-05-19 16:32:59 -04:00
error = _ ( " Unable to verify " )
2023-07-04 17:21:17 -04:00
return render (
request , " users/verify_email.html " , { " success " : False , " error " : error }
)
@login_required
2023-08-13 23:11:12 -04:00
def register ( request : AuthedHttpRequest ) :
2023-07-04 17:21:17 -04:00
form = None
if settings . MASTODON_ALLOW_ANY_SITE :
form = RegistrationForm ( request . POST )
form . instance = (
User . objects . get ( pk = request . user . pk )
if request . user . is_authenticated
else None
)
if request . method == " GET " or not form :
return render ( request , " users/register.html " , { " form " : form } )
elif request . method == " POST " :
username_changed = False
email_cleared = False
if not form . is_valid ( ) :
return render ( request , " users/register.html " , { " form " : form } )
2023-08-13 23:11:12 -04:00
if not request . user . username and form . cleaned_data [ " username " ] :
2023-07-08 00:44:22 -04:00
if User . objects . filter (
username__iexact = form . cleaned_data [ " username " ]
) . exists ( ) :
2023-07-04 17:21:17 -04:00
return render (
request ,
" users/register.html " ,
{
" form " : form ,
2024-05-19 16:32:59 -04:00
" error " : _ ( " Username in use " ) ,
2023-07-04 17:21:17 -04:00
} ,
)
request . user . username = form . cleaned_data [ " username " ]
username_changed = True
if form . cleaned_data [ " email " ] :
2023-07-08 00:44:22 -04:00
if form . cleaned_data [ " email " ] . lower ( ) != ( request . user . email or " " ) . lower ( ) :
if User . objects . filter (
email__iexact = form . cleaned_data [ " email " ]
) . exists ( ) :
2023-07-04 17:21:17 -04:00
return render (
request ,
" users/register.html " ,
{
" form " : form ,
2024-05-19 16:32:59 -04:00
" error " : _ ( " Email in use " ) ,
2023-07-04 17:21:17 -04:00
} ,
)
request . user . pending_email = form . cleaned_data [ " email " ]
else :
request . user . pending_email = None
elif request . user . email or request . user . pending_email :
request . user . pending_email = None
request . user . email = None
email_cleared = True
request . user . save ( )
if request . user . pending_email :
django_rq . get_queue ( " mastodon " ) . enqueue (
send_verification_link ,
2023-08-13 23:11:12 -04:00
request . user . pk ,
2023-07-04 17:21:17 -04:00
" verify " ,
request . user . pending_email ,
)
2024-05-19 16:32:59 -04:00
messages . add_message (
request ,
messages . INFO ,
_ ( " Verification email is being sent, please check your inbox. " ) ,
)
2023-08-13 23:11:12 -04:00
if request . user . username and not request . user . identity_linked ( ) :
request . user . initialize ( )
2023-07-04 17:21:17 -04:00
if username_changed :
2024-05-19 16:32:59 -04:00
messages . add_message ( request , messages . INFO , _ ( " Username all set. " ) )
2023-07-04 17:21:17 -04:00
if email_cleared :
2024-05-19 16:32:59 -04:00
messages . add_message (
request , messages . INFO , _ ( " Email removed from account. " )
)
2023-07-04 17:21:17 -04:00
if request . session . get ( " new_user " ) :
del request . session [ " new_user " ]
return redirect ( request . GET . get ( " next " , reverse ( " common:home " ) ) )
2022-05-07 17:00:52 -04:00
def swap_login ( request , token , site , refresh_token ) :
2023-01-01 23:50:57 -05:00
del request . session [ " swap_login " ]
del request . session [ " swap_domain " ]
2022-05-07 17:00:52 -04:00
code , data = verify_account ( site , token )
current_user = request . user
if code == 200 and data is not None :
2023-01-01 23:50:57 -05:00
username = data [ " username " ]
2023-06-30 23:53:53 -04:00
if (
username == current_user . mastodon_username
and site == current_user . mastodon_site
) :
2023-01-01 23:50:57 -05:00
messages . add_message (
2024-05-19 16:32:59 -04:00
request ,
messages . ERROR ,
_ ( " Unable to update login information: identical identity. " ) ,
2023-01-01 23:50:57 -05:00
)
2022-05-07 17:00:52 -04:00
else :
try :
2024-04-06 00:13:50 -04:00
User . objects . get (
2023-07-08 00:44:22 -04:00
mastodon_username__iexact = username , mastodon_site__iexact = site
2023-06-30 23:53:53 -04:00
)
2023-01-01 23:50:57 -05:00
messages . add_message (
2024-05-19 16:32:59 -04:00
request ,
messages . ERROR ,
_ ( " Unable to update login information: identity in use. " ) ,
2023-01-01 23:50:57 -05:00
)
2022-05-07 17:00:52 -04:00
except ObjectDoesNotExist :
2023-06-30 23:53:53 -04:00
current_user . mastodon_username = username
2023-01-01 23:50:57 -05:00
current_user . mastodon_id = data [ " id " ]
2022-05-07 17:00:52 -04:00
current_user . mastodon_site = site
current_user . mastodon_token = token
current_user . mastodon_refresh_token = refresh_token
current_user . mastodon_account = data
2023-01-01 23:50:57 -05:00
current_user . save (
update_fields = [
" username " ,
" mastodon_id " ,
2023-06-30 23:53:53 -04:00
" mastodon_username " ,
2023-01-01 23:50:57 -05:00
" mastodon_site " ,
" mastodon_token " ,
" mastodon_refresh_token " ,
" mastodon_account " ,
]
)
django_rq . get_queue ( " mastodon " ) . enqueue (
2023-07-05 00:47:54 -04:00
refresh_mastodon_data_task , current_user . pk , token
2023-01-01 23:50:57 -05:00
)
messages . add_message (
2024-05-19 16:32:59 -04:00
request ,
messages . INFO ,
_ ( " Login information updated. " ) + f " { username } @ { site } " ,
2023-01-01 23:50:57 -05:00
)
2022-05-07 17:00:52 -04:00
else :
2024-05-19 16:32:59 -04:00
messages . add_message (
request , messages . ERROR , _ ( " Invalid account data from Mastodon instance. " )
)
2023-01-01 23:50:57 -05:00
return redirect ( reverse ( " users:data " ) )
2022-05-07 17:00:52 -04:00
2023-07-12 01:11:15 -04:00
def clear_preference_cache ( request ) :
for key in list ( request . session . keys ( ) ) :
if key . startswith ( " p_ " ) :
del request . session [ key ]
2022-05-07 17:00:52 -04:00
def auth_login ( request , user ) :
2023-01-01 23:50:57 -05:00
""" Decorates django ``login()``. Attach token to session. """
2023-06-03 19:20:30 -04:00
auth . login ( request , user , backend = " mastodon.auth.OAuth2Backend " )
2023-07-12 01:11:15 -04:00
clear_preference_cache ( request )
2023-01-01 23:50:57 -05:00
if (
user . mastodon_last_refresh < timezone . now ( ) - timedelta ( hours = 1 )
or user . mastodon_account == { }
) :
2023-07-05 00:47:54 -04:00
django_rq . get_queue ( " mastodon " ) . enqueue ( refresh_mastodon_data_task , user . pk )
2022-05-07 17:00:52 -04:00
def auth_logout ( request ) :
2023-01-01 23:50:57 -05:00
""" Decorates django ``logout()``. Release token in session. """
2022-05-07 17:00:52 -04:00
auth . logout ( request )
2023-12-10 19:38:00 -05:00
response = redirect ( " / " )
response . delete_cookie ( settings . TAKAHE_SESSION_COOKIE_NAME )
return response
2022-05-07 17:00:52 -04:00
2023-07-04 17:21:17 -04:00
def clear_data_task ( user_id ) :
user = User . objects . get ( pk = user_id )
user_str = str ( user )
2023-07-20 21:59:49 -04:00
if user . identity :
remove_data_by_user ( user . identity )
2023-12-10 19:38:00 -05:00
Takahe . delete_identity ( user . identity . pk )
2023-07-04 17:21:17 -04:00
user . clear ( )
logger . warning ( f " User { user_str } data cleared. " )
2022-05-07 17:00:52 -04:00
@login_required
def clear_data ( request ) :
2023-06-28 08:11:36 -04:00
if request . META . get ( " HTTP_AUTHORIZATION " ) :
raise BadRequest ( " Only for web login " )
2023-01-01 23:50:57 -05:00
if request . method == " POST " :
2023-07-05 00:47:54 -04:00
v = request . POST . get ( " verification " )
if v and ( v == request . user . mastodon_acct or v == request . user . email ) :
2023-07-04 17:21:17 -04:00
django_rq . get_queue ( " mastodon " ) . enqueue ( clear_data_task , request . user . id )
2023-12-10 19:38:00 -05:00
return auth_logout ( request )
2022-05-07 17:00:52 -04:00
else :
2024-05-19 16:32:59 -04:00
messages . add_message ( request , messages . ERROR , _ ( " Account mismatch. " ) )
2022-05-07 17:00:52 -04:00
return redirect ( reverse ( " users:data " ) )