diff --git a/CHANGELOG.md b/CHANGELOG.md
index 748c0c5b..9b2c47ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,46 @@
+1.2.0 / 2018-05-04
+==================
+
+**General**
+
+* Updated to Flask 1.0 & switched documentation to suggest using `flask run` instead of `python serve.py`.
+* Added the ability to make static & regex flags case insensitive.
+* The `/chals` endpoint no longer lists the details of challenges.
+ * The `/chals/:id` endpoint is now used to load challenge information before display.
+* Admins can now see what users have solved a given challenge from the admin panel.
+* Fixed issue with imports extracting files outside of the CTFd directory.
+* Added import zipfile validation and optional size restriction.
+* The ctftime, authentication, and admin restrictions have been converted to decorators to improve code reuse.
+ * 403 is now a more common status code. Previously it only indicated CSRF failure, now it can indicate login failure
+ or other Forbidden access situations.
+* Challenge previews now work consistently instead of occasionally failing to show.
+* Tests are now randomly ordered with `nose-randomly`.
+
+**Themes**
+
+* Admins now have the ability to upload a CTF logo from the config panel.
+* Switched from the `marked` library to `Markdown-It` for client side markdown rendering.
+ * This will break Challenge type plugins that override the markdown renderer since we are no longer using the marked renderers.
+* Introduced the `ezpg()` JS function to make it easier to draw a progressbar modal.
+* Introduced the `$.patch()` AJAX wrapper.
+* Team names are truncated properly to 50 characters in `teams.html`.
+* The admin panel now uses Bootstrap badges instead of buttons to indicate properties such as `admin`, `verified`, `visible`.
+
+**Plugins**
+
+* Challenge type plugins now use a global challenge object with exposed functions to specify how to display a challenge.
+(`preRender()`, `render()`, `postRender()`, `submit()`).
+ * Challenge type plugins also have access to window.challenge.data which allow for the previously mentioned functions to
+ process challenge data and change logic accordingly.
+* Challenge type plugins now get full control over how a challenge is displayed via the nunjucks files.
+* Challenge plugins should now pass the entire flag/key object to a Custom flag type.
+ * This allows the flag type to make use of the data column to decide how to operate on the flag. This is used to implement
+ case insensitive flags.
+* Challenge modals (`modal.njk`) now use `{{ description }}` instead of `{{ desc }}` properly aligning with the database schema.
+* The update and create modals now inject data into the modal via nunjucks instead of client side Javascript.
+* The `utils.base64decode()` & `utils.base64encode()` functions no longer expose url encoding/decoding parameters.
+
+
1.1.4 / 2018-04-05
==================
diff --git a/CTFd/__init__.py b/CTFd/__init__.py
index e9ade32e..913aa07d 100644
--- a/CTFd/__init__.py
+++ b/CTFd/__init__.py
@@ -17,7 +17,7 @@ if sys.version_info[0] < 3:
reload(sys)
sys.setdefaultencoding("utf-8")
-__version__ = '1.1.4'
+__version__ = '1.2.0'
class CTFdFlask(Flask):
diff --git a/CTFd/admin/__init__.py b/CTFd/admin/__init__.py
index a39bed69..78faaa4b 100644
--- a/CTFd/admin/__init__.py
+++ b/CTFd/admin/__init__.py
@@ -147,8 +147,8 @@ def admin_config():
utils.set_config("mail_username", None)
utils.set_config("mail_password", None)
- if request.files.get('ctf_logo', None):
- ctf_logo = request.files['ctf_logo']
+ if request.files.get('ctf_logo_file', None):
+ ctf_logo = request.files['ctf_logo_file']
file_id, file_loc = utils.upload_file(ctf_logo, None)
utils.set_config("ctf_logo", file_loc)
elif request.form.get('ctf_logo') == '':
diff --git a/CTFd/plugins/challenges/assets/standard-challenge-modal.js b/CTFd/plugins/challenges/assets/standard-challenge-modal.js
index f30985df..7f48e0a8 100644
--- a/CTFd/plugins/challenges/assets/standard-challenge-modal.js
+++ b/CTFd/plugins/challenges/assets/standard-challenge-modal.js
@@ -1,3 +1,5 @@
+window.challenge.data = undefined;
+
window.challenge.renderer = new markdownit({
html: true,
});
diff --git a/CTFd/themes/admin/static/js/challenges/chalboard.js b/CTFd/themes/admin/static/js/challenges/chalboard.js
index 7ab07443..3be7989b 100644
--- a/CTFd/themes/admin/static/js/challenges/chalboard.js
+++ b/CTFd/themes/admin/static/js/challenges/chalboard.js
@@ -37,6 +37,8 @@ function render_challenge_preview(chal_id){
$.get(script_root + obj.type_data.templates.modal, function (template_data) {
var template = nunjucks.compile(template_data);
+ window.challenge.data = obj;
+
window.challenge.preRender()
obj['description'] = window.challenge.render(obj['description']);
diff --git a/CTFd/themes/admin/templates/config.html b/CTFd/themes/admin/templates/config.html
index fd943e7a..b1d4d6ec 100644
--- a/CTFd/themes/admin/templates/config.html
+++ b/CTFd/themes/admin/templates/config.html
@@ -55,19 +55,20 @@
{% endif %}
-
+
+