@@ -19,7 +19,7 @@ application's functionality, including URL rounting,
1919and <a href =" /flask-app-immutabledict-examples.html " >ImmutableDict</a >
2020are several other callables with code examples from the same ` flask.app ` package.
2121
22- You should read up on these subjects along with these ` Flask ` examples:
22+ These subjects go along with the ` Flask ` code examples:
2323
2424* [ web development] ( /web-development.html ) and [ web design] ( /web-design.html )
2525* [ Flask] ( /flask.html ) and [ web framework] ( /web-frameworks.html ) concepts
@@ -88,34 +88,82 @@ as-is to run CTF events, or modified for custom rules for related
8888scenarios. CTFd is open sourced under the
8989[ Apache License 2.0] ( https://github.com/CTFd/CTFd/blob/master/LICENSE ) .
9090
91- [ ** CTFd / manage .py** ] ( https://github.com/CTFd/CTFd/blob/master/././manage .py )
91+ [ ** CTFd / tests / test_themes .py** ] ( https://github.com/CTFd/CTFd/blob/master/./tests/test_themes .py )
9292
9393``` python
94- # manage.py
95- ~~ from flask import Flask
96- from flask_sqlalchemy import SQLAlchemy
97- from flask_script import Manager
98- from flask_migrate import Migrate, MigrateCommand
99- from CTFd import create_app
100- from CTFd.utils import get_config as get_config_util, set_config as set_config_util
101- from CTFd.models import *
94+ # test_themes.py
95+
96+ from flask import request
97+ from jinja2.sandbox import SecurityError
98+ from werkzeug.test import Client
99+
100+ from CTFd.utils import get_config
101+ from tests.helpers import create_ctfd, destroy_ctfd, gen_user, login_as_user
102+
103+
104+ def test_themes_run_in_sandbox ():
105+ app = create_ctfd()
106+ with app.app_context():
107+ try :
108+ app.jinja_env.from_string(
109+ " {{ ().__class__.__bases__[0].__subclasses__()[40]('./test_utils.py').read() }} "
110+ ).render()
111+ except SecurityError:
112+ pass
113+ except Exception as e:
114+ raise e
115+ destroy_ctfd(app)
116+
117+
118+ def test_themes_cant_access_configpy_attributes ():
119+ app = create_ctfd()
120+ with app.app_context():
121+ assert app.config[" SECRET_KEY" ] == " AAAAAAAAAAAAAAAAAAAA"
122+ assert (
123+ app.jinja_env.from_string(" {{ get_config('SECRET_KEY') }} " ).render()
124+ != app.config[" SECRET_KEY" ]
125+ )
126+ destroy_ctfd(app)
127+
102128
103- app = create_app()
129+ def test_themes_escape_html ():
104130
105- manager = Manager(app)
106- manager.add_command(" db" , MigrateCommand)
131+
132+ # # ... source file abbreviated to get to Flask examples ...
133+
134+
135+
136+ r = client.get(" /challenges" )
137+ assert r.status_code == 200
138+ assert " Challenges" in r.get_data(as_text = True )
139+
140+ r = client.get(" /scoreboard" )
141+ assert r.status_code == 200
142+ assert " Scoreboard" in r.get_data(as_text = True )
143+ destroy_ctfd(app)
107144
108145
109- def jsenums ():
110- from CTFd.constants import JS_ENUMS
111- import json
112- import os
146+ def test_that_request_path_hijacking_works_properly ():
147+ app = create_ctfd(setup = False , application_root = " /ctf" )
148+ assert app.request_class.__name__ == " CTFdRequest"
149+ with app.app_context():
150+ with app.test_request_context(" /challenges" ):
151+ assert request.path == " /ctf/challenges"
152+ destroy_ctfd(app)
113153
114- path = os.path.join(app.root_path, " themes/core/assets/js/constants.js" )
154+ app = create_ctfd()
155+ assert app.request_class.__name__ == " CTFdRequest"
156+ with app.app_context():
157+ with app.test_request_context(" /challenges" ):
158+ assert request.path == " /challenges"
115159
116- with open (path, " w+" ) as f:
117- for k, v in JS_ENUMS .items():
118- f.write(" const {} = Object.freeze({} );" .format(k, json.dumps(v)))
160+ ~~ from flask import Flask
161+
162+ ~~ test_app = Flask(" test" )
163+ assert test_app.request_class.__name__ == " Request"
164+ with test_app.test_request_context(" /challenges" ):
165+ assert request.path == " /challenges"
166+ destroy_ctfd(app)
119167
120168
121169
@@ -215,7 +263,6 @@ from sqlalchemy import event
215263from sqlalchemy.engine import Engine
216264from sqlalchemy.exc import OperationalError, ProgrammingError
217265
218- from flaskbb._compat import iteritems, string_types
219266from flaskbb.extensions import (alembic, allows, babel, cache, celery, csrf,
220267 db, debugtoolbar, limiter, login_manager, mail,
221268 redis_store, themes, whooshee)
@@ -249,6 +296,7 @@ from .forum import views as forum_views # noqa
249296from .management import views as management_views # noqa
250297from .user import views as user_views # noqa
251298
299+
252300logger = logging.getLogger(__name__ )
253301
254302
@@ -740,8 +788,8 @@ def on_disconnect():
740788 disconnected = ' /'
741789
742790
743- @socketio.on ( ' connect ' , namespace = ' /test' )
744- def on_connect_test ():
791+ @socketio.event ( namespace = ' /test' )
792+ def connect ():
745793 send(' connected-test' )
746794
747795
@@ -789,10 +837,15 @@ def on_connect_test():
789837 self .assertEqual(len (received), 1 )
790838 self .assertEqual(received[0 ][' args' ], {' connected' : ' foo' })
791839
792-
793- if __name__ == ' __main__' :
794- unittest.main()
795-
840+ def test_encode_decode (self ):
841+ client = socketio.test_client(app)
842+ client.get_received()
843+ data = {' foo' : ' bar' , ' invalid' : socketio}
844+ self .assertRaises(TypeError , client.emit, ' my custom event' , data,
845+ callback = True )
846+ data = {' foo' : ' bar' }
847+ ack = client.emit(' my custom event' , data, callback = True )
848+ data[' foo' ] = ' baz'
796849
797850
798851# # ... source file continues with no further Flask examples...
0 commit comments