Merge pull request #1367 from CTFd/cache-user-ips-for-tracker

* Cache user IPs and only update IP usage on new IPs or on non-GET requests
better-spacing-without-solves
Kevin Chung 2020-04-30 16:04:46 -04:00 committed by GitHub
commit 1c10643537
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 13 deletions

View File

@ -46,6 +46,12 @@ def clear_pages():
cache.delete_memoized(get_page)
def clear_user_ips(user_id):
from CTFd.utils.user import get_user_ips
cache.delete_memoized(get_user_ips, user_id=user_id)
def clear_user_session(user_id):
from CTFd.utils.user import get_user_attrs

View File

@ -7,6 +7,7 @@ from flask import abort, redirect, render_template, request, session, url_for
from sqlalchemy.exc import IntegrityError, InvalidRequestError
from werkzeug.wsgi import DispatcherMiddleware
from CTFd.cache import clear_user_ips
from CTFd.exceptions import UserNotFoundException, UserTokenExpiredException
from CTFd.models import Tracking, db
from CTFd.utils import config, get_config, markdown
@ -41,6 +42,7 @@ from CTFd.utils.security.csrf import generate_nonce
from CTFd.utils.user import (
authed,
get_current_user_attrs,
get_current_user_ips,
get_current_team_attrs,
get_ip,
is_admin,
@ -179,20 +181,26 @@ def init_request_processors(app):
return
if authed():
track = Tracking.query.filter_by(ip=get_ip(), user_id=session["id"]).first()
if not track:
visit = Tracking(ip=get_ip(), user_id=session["id"])
db.session.add(visit)
user_ips = get_current_user_ips()
ip = get_ip()
track = None
if ip not in user_ips:
track = Tracking(ip=get_ip(), user_id=session["id"])
db.session.add(track)
else:
track.date = datetime.datetime.utcnow()
if request.method != "GET":
track = Tracking.query.filter_by(
ip=get_ip(), user_id=session["id"]
).first()
track.date = datetime.datetime.utcnow()
try:
db.session.commit()
except (InvalidRequestError, IntegrityError):
db.session.rollback()
logout_user()
db.session.close()
if track:
try:
db.session.commit()
except (InvalidRequestError, IntegrityError):
db.session.rollback()
logout_user()
clear_user_ips(user_id=session["id"])
@app.before_request
def banned():

View File

@ -7,7 +7,7 @@ from flask import request, session
from CTFd.cache import cache
from CTFd.constants.users import UserAttrs
from CTFd.constants.teams import TeamAttrs
from CTFd.models import Fails, Users, db, Teams
from CTFd.models import Fails, Users, db, Teams, Tracking
from CTFd.utils import get_config
@ -120,6 +120,23 @@ def get_ip(req=None):
return remote_addr
def get_current_user_ips():
if authed():
return get_user_ips(user_id=session["id"])
else:
return None
@cache.memoize(timeout=60)
def get_user_ips(user_id):
addrs = (
Tracking.query.with_entities(Tracking.ip.distinct())
.filter_by(user_id=user_id)
.all()
)
return [ip for ip, in addrs]
def get_wrong_submissions_per_minute(account_id):
"""
Get incorrect submissions per minute.