Miscellaneous Fixes (#1752)

* Update CHANGELOG 
* Add `registered_only` decorator
* Make team invites redirect to `/register` if you're unauthed
This commit is contained in:
Kevin Chung
2020-12-04 14:10:36 -05:00
committed by GitHub
parent d9975f307c
commit cb5ba26bdb
6 changed files with 45 additions and 5 deletions

View File

@@ -16,7 +16,6 @@
- Imports have been made more stable
- This is primarily done by killing MySQL processes that are locking metadta
- This is a subpar approach but it seems to be the only solution to avoid a metadata lock in MySQL. This approach did not appear to be needed under Postgres or SQLite
- Update some migrations to first check if a table already exists.
**API**
@@ -28,6 +27,8 @@
**Themes**
- Add Team Invite icon and Disband Team icon to teams/private.html
- Add teams/invite.html file to handle team joining with invites
- Added syntax highlighting to challenge descriptions, pages, hints, notifications, comments, and markdown editors
- This is done with `highlight.js` which has been added to `package.json`
- Fix notifications to properly fix/support Markdown and HTML notifications
@@ -41,9 +42,12 @@
- Fixed issue in `challenge.html` where the max attempts for a challenge would not show if it was set to 1
- Edit donut charts to have easier to read legends and labels
- Make data zoom bars thinner and more transparent
- Add logo, banner, and favicon settings to the setup.html
**Plugins**
- The `auth.register` (`/register`) endpoint now accepts a `?next=` parameter to define where to redirect to after registration
- There is now a `registered_only` decorator to redirect users to `auth.register` (`/register`) instead of `auth.login` (`/login`)
- Don't run `db.create_all()` as much during plugin upgrade or during imports
- By avoiding this we can let alembic and migrations do more of the table creation work but this means that plugins specifically opt into `app.db.create_all()` and will not implicitly get it through `upgrade()`.
- This means plugins that run `upgrade()` without a migrations folder (no idea who would do this really) will need to upgrade their code.

View File

@@ -185,6 +185,9 @@ def reset_password(data=None):
@ratelimit(method="POST", limit=10, interval=5)
def register():
errors = get_errors()
if current_user.authed():
return redirect(url_for("challenges.listing"))
if request.method == "POST":
name = request.form.get("name", "").strip()
email_address = request.form.get("email", "").strip().lower()
@@ -309,6 +312,11 @@ def register():
login_user(user)
if request.args.get("next") and validators.is_safe_url(
request.args.get("next")
):
return redirect(request.args.get("next"))
if config.can_send_mail() and get_config(
"verify_emails"
): # Confirming users is enabled and we can send email.

View File

@@ -5,7 +5,7 @@ from CTFd.exceptions import TeamTokenExpiredException, TeamTokenInvalidException
from CTFd.models import TeamFieldEntries, TeamFields, Teams, db
from CTFd.utils import config, get_config, validators
from CTFd.utils.crypto import verify_password
from CTFd.utils.decorators import authed_only, ratelimit
from CTFd.utils.decorators import authed_only, ratelimit, registered_only
from CTFd.utils.decorators.modes import require_team_mode
from CTFd.utils.decorators.visibility import (
check_account_visibility,
@@ -53,7 +53,7 @@ def listing():
@teams.route("/teams/invite", methods=["GET", "POST"])
@authed_only
@registered_only
@require_team_mode
def invite():
infos = get_infos()

View File

@@ -130,6 +130,9 @@
<small class="form-text text-muted">
Share this link with your team members for them to join your team
</small>
<small class="form-text text-muted">
Invite links can be re-used and expire after 1 day
</small>
</div>
</form>
{% endwith %}

View File

@@ -97,6 +97,29 @@ def authed_only(f):
return authed_only_wrapper
def registered_only(f):
"""
Decorator that requires the user to have a registered account
:param f:
:return:
"""
@functools.wraps(f)
def _registered_only(*args, **kwargs):
if authed():
return f(*args, **kwargs)
else:
if (
request.content_type == "application/json"
or request.accept_mimetypes.best == "text/event-stream"
):
abort(403)
else:
return redirect(url_for("auth.register", next=request.full_path))
return _registered_only
def admins_only(f):
"""
Decorator that requires the user to be authenticated and an admin

View File

@@ -18,11 +18,12 @@ def test_new_fields_show_on_pages():
gen_field(app.db)
with login_as_user(app) as client:
with app.test_client() as client:
r = client.get("/register")
assert "CustomField" in r.get_data(as_text=True)
assert "CustomFieldDescription" in r.get_data(as_text=True)
with login_as_user(app) as client:
r = client.get("/settings")
assert "CustomField" in r.get_data(as_text=True)
assert "CustomFieldDescription" in r.get_data(as_text=True)
@@ -101,7 +102,7 @@ def test_fields_properties():
app.db, name="CustomField4", required=False, public=False, editable=False
)
with login_as_user(app) as client:
with app.test_client() as client:
r = client.get("/register")
resp = r.get_data(as_text=True)
assert "CustomField1" in resp
@@ -109,6 +110,7 @@ def test_fields_properties():
assert "CustomField3" in resp
assert "CustomField4" in resp
with login_as_user(app) as client:
r = client.get("/settings")
resp = r.get_data(as_text=True)
assert "CustomField1" in resp