2.1.4 / 2019-08-30
==================
**General**
* Make user pages show the team's score and place information instead of the user's information if in team mode
* Allow admins to search users by IP address
* Require password for email address changes in the user profile
* The place indicator in `Teams Mode` on the team pages and user pages now correctly excludes hidden teams
* Fix scoreboard place ordinalization in Python 3
* Fix for a crash where imports will fail on SQLite due to lack of ALTER command support
* Fix for an issue where files downloaded via S3 would have the folder name in the filename
* Make `Users.get_place()` and `Teams.get_place()` for return None instead of 0 if the account has no rank/place
* Properly redirect users or 403 if the endpoint requires a team but the user isn't in one
* Show affiliation in user and team pages in the admin panel and public and private user and team pages
**Themes**
* Remove invalid `id='submit'` on submit buttons in various theme files
* Set `tabindex` to 0 since we don't really care for forcing tab order
* Rename `statistics.js` to `graphs.js` in the Admin Panel as it was identified that adblockers can sometimes block the file
**API**
* The team profile endpoint (`/api/v1/teams/me`) will now return 403 instead of 400 if the requesting user is not the captain
* The Challenge API will now properly freeze the solve count to freeze time
* The place indicator in Team Mode on the team pages and user pages now excludes counting hidden teams.
* Updated `flask-marshmallow` to 0.10.1, `marshmallow-sqlalchemy` to 0.17.0
* Pinned `marshmallow` to 2.20.2
* Closes#1093
* Closes#1088
* Show affiliation in user and team pages in the admin panel and public and private user and team pages.
* Make user pages show team information (score, place) instead of user information if in team mode.
* Make `Users.get_place()` and `Teams.get_place()` for return None instead of 0 if the account has no rank. (Closes#1039)
* Make `populate.py` randomly add affiliations and officials
* Only add `teams.team_captain_id` foreign key if the db backend isn't SQLite. SQLite does not support ALTER for the manipulation of columns/constraints.
* Closes#1041
2.1.3 / 2019-06-22
==================
**General**
* Fix issue with downloading files after CTF end when `view_after_ctf` is enabled
* Sort solves in admin challenge view by date
* Link to appropriate user and challenge in team, user, and challenge pages
* Redirect to `/team` instead of `/challenges` after a user registers in team mode
* Fixes bug where pages marked as `hidden` weren't loading
* Remove `data-href` from `pages.html` in the Admin Panel to fix the delete button
* Add UI to handle team member removal in Admin Panel
* Fixes account links on the scoreboard page created by `update()`. They now correctly point to the user instead of undefined when in user mode.
* `utils._get_config` will now return `KeyError` instead of `None` to avoid cache misses
**Deployment**
* Use `/dev/shm` for `--worker-tmp-dir` in gunicorn in Docker
* Cache `get_place` code for users and teams.
* Install `Flask-DebugToolbar` in development
* Cache the `/scoreboard` page to avoid having to rebuild the response so often
* Make unprivileged `ctfd` user usable for mysql connection in docker-compose by having the db image create the database instead of CTFd
* Fix bug causing apache2 + mod_wsgi deployments to break
**API**
* Change `/api/v1/teams/[team_id]/members` from taking `id` to `user_id`.
* Endpoint was unused so the API change is considered non-breaking.
* Add `account_type` and `account_url` field in `/api/v1/scoreboard`
* Separate `/api/v1/[users,teams]/[me,id]/[solves,fails,awards]` into seperate API endpoints
* Clear standings cache after award creation/deletion
**Exports**
* Temporarily disable foreign keys in MySQL, MariaDB, and Postgres during `import_ctf()`
* Add `cache_timeout` parameter to `send_file`response in `/admin/export` to prevent the browser from caching the export
**Tests**
* Fix score changing test helpers to clear standings cache when generating a score changing row
* Fixes account links on the scoreboard page created by `update()`. They now correctly point to the user instead of undefined when in user mode.
* Add `account_type` and `account_url` field in `/api/v1/scoreboard`
* Temporarily disable foreign keys in MySQL, MariaDB, and Postgres during `import_ctf()`
* Likely also disables SQLite but SQLite is permissive about foreign keys to begin with so irrelevant.
* Create a `flask_migrate.stamp()` wrapper in `CTFd.utils.migrations` that always references the migrations folder regardless of how CTFd is run or deployed.
* Closes#257 properly
* Cache the `/scoreboard` page to avoid having to rebuild the response so often
* Update `tests.api.v1.test_scoreboard:test_scoreboard_is_cached` to also test if `/scoreboard` is cached
* Cache get place code for users and teams.
* Fix score changing test helpers to clear standings cache when generating a score changing row
* `utils._get_config` will now return `KeyError` instead of None.
* Separate `/api/v1/[users,teams]/[me,id]/[solves,fails,awards]` into seperate API endpoints
* Install `Flask-DebugToolbar` in development
Main goals covered in #1012
* Change `/api/v1/teams/[team_id]/members` from taking `id` to `user_id`.
* Not even the admin panel was using this endpoint so doesn't seem that drastic of a change
* Add UI to handle team member removal
* Remove `data-href` from `pages.html` to fix the delete button
* The delete action propagates too much causing issues. This should be re-implemented on page editor rewrite.
* Fixes bug where pages marked as `hidden` weren't loading
* It's possible that some users used this behavior however this fix implements the correct behavior. The `draft` setting can be used to completely hide pages.
2.1.2 / 2019-05-13
==================
**General**
* Fix freeze time regressions in 2.x
* Make `/api/v1/[users,teams]/[me]/[solves,fails,awards]` endpoints load as admin so users can see their solves after freeze
* Make `/api/v1/challenges/[id]/solves` only show solves before freeze time
* Add the `?preview=true` GET parameter for admins to preview challenges solves as a user
* Team join attempts are now ratelimited
**Tests**
* More linting and autoformatting rules
* Format Javascript and CSS files with `prettier`: `prettier --write 'CTFd/themes/**/*'`
* Format Python with `black`: `black CTFd` and `black tests`
* `make lint` and thus Travis now include the above commands as lint checks
* Travis now uses xenial instead of trusty.
* Format Javascript and CSS files with `prettier`: `prettier --write 'CTFd/themes/**/*'`
* Format Python with `black`: `black CTFd` & `black tests`
* Travis now uses xenial instead of trusty.
* Fix freeze time regressions in 2.x
* Make `/api/v1/[users,teams]/[me,id]/[solves,fails,awards]` endpoints load as admin to load all rows and bypass freeze
* Closes#988
* Make `/api/v1/challenges/[id]/solves` respect freeze time. `/api/v1/challenges/[id]/solves?preview=true` is exposed for admins to see solves as a user would.
* Closes#986
2.1.1 / 2019-05-04
==================
**General**
* Allow admins to hit `/api/v1/challenges` and `/api/v1/challenges/[id]` without having a team to fix challenge previews
* Fix rate-limiting of flag submission when using team mode
* Fixes some modal close buttons not working in the admin panel
* Fixes `populate.py` to assign captains to teams.
**Models**
* Added `Challenges.flags` relationship and moved the `Flags.challenge` relationship to a backref on Challenges
* Added `ondelete='CASCADE'` to most ForeignKeys in models allowing for deletions to remove associated data
* `Hints` should be deleted when their Challenge is deleted
* `Tags` should be deleted when their Challenge is deleted
* `Flags` should be deleted when their Challenge is deleted
* `ChallengeFiles` should be deleted when their Challenge is deleted
* Deletion of the file itself is not handled by the model/database
* `Awards` should be deleted when their user or team is deleted
* `Unlocks` should be deleted when their user or team is deleted
* `Tracking` should be deleted when their user or team is deleted
* `Teams.captain_id` should be set to NULL when the captain user is deleted
**Exports**
* Force `db.create_all()` to happen for imports on `sqlite` or on failure to create missing tables
* Force `ctf_theme` to be set to `core` in imports in case a theme is missing from the import or the instance
* Fix imports/exports to emit and accept JSON properly under MariaDB
* MariaDB does not properly understand JSON so it must accept strings instead of dicts
* MariaDB outputs strings instead of JSON for its JSON type so the export serializer will attempt to cast output JSON strings to JSON objects
**Deployment**
* Run as root when using docker-compose
* This is necessary to be able to write to the volumes mounted from the host