mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-18 14:34:21 +01:00
929 better visibility constants (#1490)
* Adds Enums for visibility configs for better reusability. Old tests will continue to use the static values but new ones should use the enum values. * Closes #929
This commit is contained in:
@@ -1,7 +1,42 @@
|
||||
import json
|
||||
|
||||
from CTFd.constants import JinjaEnum, RawEnum
|
||||
from CTFd.utils import get_config
|
||||
from CTFd.utils.helpers import markup
|
||||
|
||||
|
||||
class ConfigTypes(str, RawEnum):
|
||||
CHALLENGE_VISIBILITY = "challenge_visibility"
|
||||
SCORE_VISIBILITY = "score_visibility"
|
||||
ACCOUNT_VISIBILITY = "account_visibility"
|
||||
REGISTRATION_VISIBILITY = "registration_visibility"
|
||||
|
||||
|
||||
@JinjaEnum
|
||||
class ChallengeVisibilityTypes(str, RawEnum):
|
||||
PUBLIC = "public"
|
||||
PRIVATE = "private"
|
||||
ADMINS = "admins"
|
||||
|
||||
|
||||
@JinjaEnum
|
||||
class ScoreVisibilityTypes(str, RawEnum):
|
||||
PUBLIC = "public"
|
||||
PRIVATE = "private"
|
||||
HIDDEN = "hidden"
|
||||
ADMINS = "admins"
|
||||
|
||||
|
||||
@JinjaEnum
|
||||
class AccountVisibilityTypes(str, RawEnum):
|
||||
PUBLIC = "public"
|
||||
PRIVATE = "private"
|
||||
ADMINS = "admins"
|
||||
|
||||
|
||||
@JinjaEnum
|
||||
class RegistrationVisibilityTypes(str, RawEnum):
|
||||
PUBLIC = "public"
|
||||
PRIVATE = "private"
|
||||
|
||||
|
||||
class _ConfigsWrapper:
|
||||
@@ -14,10 +49,14 @@ class _ConfigsWrapper:
|
||||
|
||||
@property
|
||||
def theme_header(self):
|
||||
from CTFd.utils.helpers import markup
|
||||
|
||||
return markup(get_config("theme_header", default=""))
|
||||
|
||||
@property
|
||||
def theme_footer(self):
|
||||
from CTFd.utils.helpers import markup
|
||||
|
||||
return markup(get_config("theme_footer", default=""))
|
||||
|
||||
@property
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from enum import Enum
|
||||
|
||||
import cmarkgfm
|
||||
from flask import current_app as app
|
||||
|
||||
@@ -43,6 +45,10 @@ def _get_config(key):
|
||||
|
||||
|
||||
def get_config(key, default=None):
|
||||
# Convert enums to raw string values to cache better
|
||||
if isinstance(key, Enum):
|
||||
key = str(key)
|
||||
|
||||
value = _get_config(key)
|
||||
if value is KeyError:
|
||||
return default
|
||||
@@ -58,5 +64,10 @@ def set_config(key, value):
|
||||
config = Configs(key=key, value=value)
|
||||
db.session.add(config)
|
||||
db.session.commit()
|
||||
|
||||
# Convert enums to raw string values to cache better
|
||||
if isinstance(key, Enum):
|
||||
key = str(key)
|
||||
|
||||
cache.delete_memoized(_get_config, key)
|
||||
return config
|
||||
|
||||
@@ -1,44 +1,51 @@
|
||||
from CTFd.constants.config import (
|
||||
AccountVisibilityTypes,
|
||||
ChallengeVisibilityTypes,
|
||||
ConfigTypes,
|
||||
RegistrationVisibilityTypes,
|
||||
ScoreVisibilityTypes,
|
||||
)
|
||||
from CTFd.utils import get_config
|
||||
from CTFd.utils.user import authed, is_admin
|
||||
|
||||
|
||||
def challenges_visible():
|
||||
v = get_config("challenge_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.CHALLENGE_VISIBILITY)
|
||||
if v == ChallengeVisibilityTypes.PUBLIC:
|
||||
return True
|
||||
elif v == "private":
|
||||
elif v == ChallengeVisibilityTypes.PRIVATE:
|
||||
return authed()
|
||||
elif v == "admins":
|
||||
elif v == ChallengeVisibilityTypes.ADMINS:
|
||||
return is_admin()
|
||||
|
||||
|
||||
def scores_visible():
|
||||
v = get_config("score_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.SCORE_VISIBILITY)
|
||||
if v == ScoreVisibilityTypes.PUBLIC:
|
||||
return True
|
||||
elif v == "private":
|
||||
elif v == ScoreVisibilityTypes.PRIVATE:
|
||||
return authed()
|
||||
elif v == "hidden":
|
||||
elif v == ScoreVisibilityTypes.HIDDEN:
|
||||
return False
|
||||
elif v == "admins":
|
||||
elif v == ScoreVisibilityTypes.ADMINS:
|
||||
return is_admin()
|
||||
|
||||
|
||||
def accounts_visible():
|
||||
v = get_config("account_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.ACCOUNT_VISIBILITY)
|
||||
if v == AccountVisibilityTypes.PUBLIC:
|
||||
return True
|
||||
elif v == "private":
|
||||
elif v == AccountVisibilityTypes.PRIVATE:
|
||||
return authed()
|
||||
elif v == "admins":
|
||||
elif v == AccountVisibilityTypes.ADMINS:
|
||||
return is_admin()
|
||||
|
||||
|
||||
def registration_visible():
|
||||
v = get_config("registration_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.REGISTRATION_VISIBILITY)
|
||||
if v == RegistrationVisibilityTypes.PUBLIC:
|
||||
return True
|
||||
elif v == "private":
|
||||
elif v == RegistrationVisibilityTypes.PRIVATE:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -2,6 +2,13 @@ import functools
|
||||
|
||||
from flask import abort, redirect, render_template, request, url_for
|
||||
|
||||
from CTFd.constants.config import (
|
||||
AccountVisibilityTypes,
|
||||
ChallengeVisibilityTypes,
|
||||
ConfigTypes,
|
||||
RegistrationVisibilityTypes,
|
||||
ScoreVisibilityTypes,
|
||||
)
|
||||
from CTFd.utils import get_config
|
||||
from CTFd.utils.user import authed, is_admin
|
||||
|
||||
@@ -9,11 +16,11 @@ from CTFd.utils.user import authed, is_admin
|
||||
def check_score_visibility(f):
|
||||
@functools.wraps(f)
|
||||
def _check_score_visibility(*args, **kwargs):
|
||||
v = get_config("score_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.SCORE_VISIBILITY)
|
||||
if v == ScoreVisibilityTypes.PUBLIC:
|
||||
return f(*args, **kwargs)
|
||||
|
||||
elif v == "private":
|
||||
elif v == ScoreVisibilityTypes.PRIVATE:
|
||||
if authed():
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
@@ -22,13 +29,13 @@ def check_score_visibility(f):
|
||||
else:
|
||||
return redirect(url_for("auth.login", next=request.full_path))
|
||||
|
||||
elif v == "hidden":
|
||||
elif v == ScoreVisibilityTypes.HIDDEN:
|
||||
return (
|
||||
render_template("errors/403.html", error="Scores are currently hidden"),
|
||||
403,
|
||||
)
|
||||
|
||||
elif v == "admins":
|
||||
elif v == ScoreVisibilityTypes.ADMINS:
|
||||
if is_admin():
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
@@ -40,11 +47,11 @@ def check_score_visibility(f):
|
||||
def check_challenge_visibility(f):
|
||||
@functools.wraps(f)
|
||||
def _check_challenge_visibility(*args, **kwargs):
|
||||
v = get_config("challenge_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.CHALLENGE_VISIBILITY)
|
||||
if v == ChallengeVisibilityTypes.PUBLIC:
|
||||
return f(*args, **kwargs)
|
||||
|
||||
elif v == "private":
|
||||
elif v == ChallengeVisibilityTypes.PRIVATE:
|
||||
if authed():
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
@@ -53,7 +60,7 @@ def check_challenge_visibility(f):
|
||||
else:
|
||||
return redirect(url_for("auth.login", next=request.full_path))
|
||||
|
||||
elif v == "admins":
|
||||
elif v == ChallengeVisibilityTypes.ADMINS:
|
||||
if is_admin():
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
@@ -68,11 +75,11 @@ def check_challenge_visibility(f):
|
||||
def check_account_visibility(f):
|
||||
@functools.wraps(f)
|
||||
def _check_account_visibility(*args, **kwargs):
|
||||
v = get_config("account_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.ACCOUNT_VISIBILITY)
|
||||
if v == AccountVisibilityTypes.PUBLIC:
|
||||
return f(*args, **kwargs)
|
||||
|
||||
elif v == "private":
|
||||
elif v == AccountVisibilityTypes.PRIVATE:
|
||||
if authed():
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
@@ -81,7 +88,7 @@ def check_account_visibility(f):
|
||||
else:
|
||||
return redirect(url_for("auth.login", next=request.full_path))
|
||||
|
||||
elif v == "admins":
|
||||
elif v == AccountVisibilityTypes.ADMINS:
|
||||
if is_admin():
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
@@ -93,10 +100,10 @@ def check_account_visibility(f):
|
||||
def check_registration_visibility(f):
|
||||
@functools.wraps(f)
|
||||
def _check_registration_visibility(*args, **kwargs):
|
||||
v = get_config("registration_visibility")
|
||||
if v == "public":
|
||||
v = get_config(ConfigTypes.REGISTRATION_VISIBILITY)
|
||||
if v == RegistrationVisibilityTypes.PUBLIC:
|
||||
return f(*args, **kwargs)
|
||||
elif v == "private":
|
||||
elif v == RegistrationVisibilityTypes.PRIVATE:
|
||||
abort(404)
|
||||
|
||||
return _check_registration_visibility
|
||||
|
||||
@@ -20,12 +20,6 @@ from CTFd.utils.config import (
|
||||
is_setup,
|
||||
)
|
||||
from CTFd.utils.config.pages import get_pages
|
||||
from CTFd.utils.config.visibility import (
|
||||
accounts_visible,
|
||||
challenges_visible,
|
||||
registration_visible,
|
||||
scores_visible,
|
||||
)
|
||||
from CTFd.utils.countries import get_countries, lookup_country_code
|
||||
from CTFd.utils.dates import isoformat, unix_time, unix_time_millis
|
||||
from CTFd.utils.events import EventManager, RedisEventManager
|
||||
@@ -61,6 +55,12 @@ def init_template_globals(app):
|
||||
from CTFd.constants.plugins import Plugins
|
||||
from CTFd.constants.sessions import Session
|
||||
from CTFd.forms import Forms
|
||||
from CTFd.utils.config.visibility import (
|
||||
accounts_visible,
|
||||
challenges_visible,
|
||||
registration_visible,
|
||||
scores_visible,
|
||||
)
|
||||
|
||||
app.jinja_env.globals.update(config=config)
|
||||
app.jinja_env.globals.update(get_pages=get_pages)
|
||||
|
||||
@@ -7,6 +7,13 @@ from flask.helpers import safe_join
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from CTFd.cache import cache
|
||||
from CTFd.constants.config import (
|
||||
AccountVisibilityTypes,
|
||||
ChallengeVisibilityTypes,
|
||||
ConfigTypes,
|
||||
RegistrationVisibilityTypes,
|
||||
ScoreVisibilityTypes,
|
||||
)
|
||||
from CTFd.models import (
|
||||
Admins,
|
||||
Files,
|
||||
@@ -156,10 +163,14 @@ def setup():
|
||||
page = Pages(title=None, route="index", content=index, draft=False)
|
||||
|
||||
# Visibility
|
||||
set_config("challenge_visibility", "private")
|
||||
set_config("registration_visibility", "public")
|
||||
set_config("score_visibility", "public")
|
||||
set_config("account_visibility", "public")
|
||||
set_config(
|
||||
ConfigTypes.CHALLENGE_VISIBILITY, ChallengeVisibilityTypes.PRIVATE
|
||||
)
|
||||
set_config(
|
||||
ConfigTypes.REGISTRATION_VISIBILITY, RegistrationVisibilityTypes.PUBLIC
|
||||
)
|
||||
set_config(ConfigTypes.SCORE_VISIBILITY, ScoreVisibilityTypes.PUBLIC)
|
||||
set_config(ConfigTypes.ACCOUNT_VISIBILITY, AccountVisibilityTypes.PUBLIC)
|
||||
|
||||
# Verify emails
|
||||
set_config("verify_emails", None)
|
||||
@@ -354,7 +365,7 @@ def files(path):
|
||||
|
||||
# Check user is admin if challenge_visibility is admins only
|
||||
if (
|
||||
get_config("challenge_visibility") == "admins"
|
||||
get_config(ConfigTypes.CHALLENGE_VISIBILITY) == "admins"
|
||||
and user.type != "admin"
|
||||
):
|
||||
abort(403)
|
||||
|
||||
Reference in New Issue
Block a user