forked from MarseyWorld/MarseyWorld
band-aid fix for frozen session issue on signup (#50)
through some reason or another, people are somehow getting cookies that aren't prepended with a dot. this is a problem because both sessions at, as best as I can tell, mix so it tries to read from a different cookie than we write to. this essentially "freezes" the session in place. users are unable to login, logout, signup, toggle poor mode, toggle NSFW, etc. ~~this attempts to delete bad session cookies (i.e. cookies with a domain that don't start with a dot).~~ ~~we don't do this on "dotless" domains (and by extension localhost) because browser support for setting cookies on FQDNs that only have one dot has tenuous support among browsers anyway).~~ ~~this *may* log some people out, but... their days of being able to do stuff on the site were numbered anyway.~~ **edit: as amazing as this thought was, browsers just wipe the entire cookies completely and there's no way to specifically target dotless cookies. for an issue that affects a few users, better to just tell them to clear their cookies. if *this* doesn't work, delete service-worker.js and be done with the whole service worker crap. forever. permanently. this PR also includes some QOL improvements.** Co-authored-by: justcool393 <justcool393@gmail.com> Reviewed-on: rDrama/rDrama#50 Co-authored-by: justcool393 <justcool393@noreply.fsdfsd.net> Co-committed-by: justcool393 <justcool393@noreply.fsdfsd.net>master
parent
c12bf5105f
commit
6dbad04f08
|
@ -25,16 +25,25 @@ app.jinja_env.auto_reload = True
|
|||
app.jinja_env.add_extension('jinja2.ext.do')
|
||||
faulthandler.enable()
|
||||
|
||||
def _startup_check():
|
||||
'''
|
||||
Performs some sanity checks on startup to make sure we aren't attempting
|
||||
to startup with obviously invalid values that won't work anyway
|
||||
'''
|
||||
if not SITE: raise TypeError("SITE environment variable must exist and not be None")
|
||||
if SITE.startswith('.'): raise ValueError("Domain must not start with a dot")
|
||||
|
||||
app.config['SERVER_NAME'] = SITE
|
||||
app.config['SECRET_KEY'] = environ.get('SECRET_KEY').strip()
|
||||
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 3153600
|
||||
_startup_check()
|
||||
if not IS_LOCALHOST:
|
||||
app.config['SESSION_COOKIE_DOMAIN'] = f'.{SITE}'
|
||||
app.config["SESSION_COOKIE_SECURE"] = True
|
||||
|
||||
app.config["SESSION_COOKIE_NAME"] = "session_" + environ.get("SITE_NAME").strip().lower()
|
||||
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024
|
||||
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
|
||||
app.config["PERMANENT_SESSION_LIFETIME"] = 60 * 60 * 24 * 365
|
||||
app.config["PERMANENT_SESSION_LIFETIME"] = SESSION_LIFETIME
|
||||
app.config['SESSION_REFRESH_EACH_REQUEST'] = False
|
||||
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
|
|
|
@ -68,6 +68,8 @@ REDDIT_NOTIFS_CACHE_KEY = "reddit_notifications"
|
|||
MARSEYS_CACHE_KEY = "marseys"
|
||||
EMOJIS_CACHE_KEY = "emojis"
|
||||
|
||||
SESSION_LIFETIME = 60 * 60 * 24 * 365
|
||||
|
||||
CASINO_RELEASE_DAY = 1662825600
|
||||
|
||||
if SITE_NAME == 'rDrama': patron = 'Paypig'
|
||||
|
|
|
@ -14,6 +14,9 @@ def session_init():
|
|||
@app.before_request
|
||||
def before_request():
|
||||
g.desires_auth = False
|
||||
if not IS_LOCALHOST:
|
||||
app.config["COOKIE_DOMAIN"] = f".{request.host}"
|
||||
app.config["SESSION_COOKIE_DOMAIN"] = app.config["COOKIE_DOMAIN"]
|
||||
if SITE == 'marsey.world' and request.path != '/kofi':
|
||||
abort(404)
|
||||
|
||||
|
@ -50,25 +53,43 @@ def before_request():
|
|||
limiter.check()
|
||||
g.db = db_session()
|
||||
|
||||
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
def after_request(response:Response):
|
||||
if response.status_code < 400:
|
||||
if CLOUDFLARE_AVAILABLE and CLOUDFLARE_COOKIE_VALUE and g.desires_auth:
|
||||
logged_in = bool(getattr(g, 'v', None))
|
||||
response.set_cookie("lo", CLOUDFLARE_COOKIE_VALUE if logged_in else '',
|
||||
max_age=60*60*24*365 if logged_in else 1, samesite="Lax")
|
||||
if getattr(g, 'db', None):
|
||||
g.db.commit()
|
||||
g.db.close()
|
||||
del g.db
|
||||
_set_cloudflare_cookie(response)
|
||||
_commit_and_close_db()
|
||||
return response
|
||||
|
||||
|
||||
@app.teardown_appcontext
|
||||
def teardown_request(error):
|
||||
if getattr(g, 'db', None):
|
||||
g.db.rollback()
|
||||
g.db.close()
|
||||
del g.db
|
||||
_rollback_and_close_db()
|
||||
stdout.flush()
|
||||
|
||||
def _set_cloudflare_cookie(response:Response) -> None:
|
||||
'''
|
||||
Sets a cookie that can be used by an upstream DDoS protection and caching provider
|
||||
'''
|
||||
if not g.desires_auth: return
|
||||
if not CLOUDFLARE_AVAILABLE or not CLOUDFLARE_COOKIE_VALUE: return
|
||||
logged_in = bool(getattr(g, 'v', None))
|
||||
if not logged_in and request.cookies.get("lo"):
|
||||
response.delete_cookie("lo", domain=app.config["COOKIE_DOMAIN"], samesite="Lax")
|
||||
elif logged_in and not request.cookies.get("lo"):
|
||||
response.set_cookie("lo", CLOUDFLARE_COOKIE_VALUE if logged_in else '',
|
||||
max_age=SESSION_LIFETIME, samesite="Lax",
|
||||
domain=app.config["COOKIE_DOMAIN"])
|
||||
|
||||
def _commit_and_close_db() -> bool:
|
||||
if not getattr(g, 'db', None): return False
|
||||
g.db.commit()
|
||||
g.db.close()
|
||||
del g.db
|
||||
return True
|
||||
|
||||
def _rollback_and_close_db() -> bool:
|
||||
if not getattr(g, 'db', None): return False
|
||||
g.db.rollback()
|
||||
g.db.close()
|
||||
del g.db
|
||||
return True
|
||||
|
|
|
@ -205,8 +205,20 @@ def sign_up_post(v:Optional[User]):
|
|||
form_timestamp = request.values.get("now", '0')
|
||||
form_formkey = request.values.get("formkey", "none")
|
||||
|
||||
def signup_error(error, clear=False):
|
||||
args = {"error": error}
|
||||
if request.values.get("referred_by"):
|
||||
user = get_account(request.values.get("referred_by"), include_shadowbanned=False)
|
||||
if user: args["ref"] = user.username
|
||||
resp = make_response(redirect(f"/signup?{urlencode(args)}"))
|
||||
if clear:
|
||||
session.clear()
|
||||
resp.delete_cookie(app.config["SESSION_COOKIE_NAME"], httponly=True, secure=True, samesite="Lax")
|
||||
return resp
|
||||
|
||||
submitted_token = session.get("signup_token", "")
|
||||
if not submitted_token: abort(400)
|
||||
if not submitted_token:
|
||||
return signup_error(f"An error occurred while attempting to signup. If you get this repeatedly, please make sure cookies are enabled.", clear=True)
|
||||
|
||||
correct_formkey_hashstr = form_timestamp + submitted_token + g.agent
|
||||
correct_formkey = hmac.new(key=bytes(SECRET_KEY, "utf-16"),
|
||||
|
@ -219,15 +231,6 @@ def sign_up_post(v:Optional[User]):
|
|||
if not username: abort(400)
|
||||
username = username.strip()
|
||||
|
||||
def signup_error(error):
|
||||
|
||||
args = {"error": error}
|
||||
if request.values.get("referred_by"):
|
||||
user = get_account(request.values.get("referred_by"), include_shadowbanned=False)
|
||||
if user: args["ref"] = user.username
|
||||
|
||||
return redirect(f"/signup?{urlencode(args)}")
|
||||
|
||||
if now - int(form_timestamp) < 5:
|
||||
return signup_error("There was a problem. Please try again.")
|
||||
|
||||
|
|
|
@ -16,14 +16,11 @@
|
|||
<h2>{% block authtitle %}{% endblock %}</h2>
|
||||
<p class="text-muted mb-md-5">{% block authtext %}{% endblock %}</p>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
|
||||
<div class="alert alert-danger fade show d-flex my-3" role="alert">
|
||||
<i class="fas fa-exclamation-circle my-auto"></i>
|
||||
<span>
|
||||
{{error}}
|
||||
</span>
|
||||
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true"><i class="far fa-times"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
|
|
|
@ -58,11 +58,8 @@
|
|||
</p>
|
||||
<hr>
|
||||
{% endif %}
|
||||
|
||||
<form action="/signup" method="post" class="mt-md-3" id="signup">
|
||||
|
||||
{% if error %}<div class="text-danger mb-2">{{error}}</div>{% endif %}
|
||||
|
||||
<input type="hidden" name="formkey" value="{{formkey}}">
|
||||
<input type="hidden" name="now" value="{{now}}">
|
||||
{% if redirect %}<input type="hidden" name="redirect" value="{{redirect}}">{% endif %}
|
||||
|
|
Loading…
Reference in New Issue