@@ -93,11 +93,17 @@ scenarios. CTFd is open sourced under the
9393``` python
9494# test_themes.py
9595
96- from flask import request
96+ import os
97+ import shutil
98+
99+ import pytest
100+ from flask import render_template, render_template_string, request
101+ from jinja2.exceptions import TemplateNotFound
97102from jinja2.sandbox import SecurityError
98103from werkzeug.test import Client
99104
100- from CTFd.utils import get_config
105+ from CTFd.config import TestingConfig
106+ from CTFd.utils import get_config, set_config
101107from tests.helpers import create_ctfd, destroy_ctfd, gen_user, login_as_user
102108
103109
@@ -121,12 +127,6 @@ def test_themes_cant_access_configpy_attributes():
121127 assert app.config[" SECRET_KEY" ] == " AAAAAAAAAAAAAAAAAAAA"
122128 assert (
123129 app.jinja_env.from_string(" {{ get_config('SECRET_KEY') }} " ).render()
124- != app.config[" SECRET_KEY" ]
125- )
126- destroy_ctfd(app)
127-
128-
129- def test_themes_escape_html ():
130130
131131
132132# # ... source file abbreviated to get to Flask examples ...
@@ -166,6 +166,25 @@ def test_that_request_path_hijacking_works_properly():
166166 destroy_ctfd(app)
167167
168168
169+ def test_theme_fallback_config():
170+ app = create_ctfd()
171+ try :
172+ os.mkdir(os.path.join(app.root_path, " themes" , " foo" ))
173+ except OSError :
174+ pass
175+
176+ with app.app_context():
177+ set_config(" ctf_theme" , " foo" )
178+ assert app.config[" THEME_FALLBACK" ] == False
179+ with app.test_client() as client:
180+ try :
181+ r = client.get(" /" )
182+ except TemplateNotFound:
183+ pass
184+ try :
185+ r = client.get(" /themes/foo/static/js/pages/main.dev.js" )
186+ except TemplateNotFound:
187+
169188
170189# # ... source file continues with no further Flask examples...
171190
@@ -185,49 +204,66 @@ forms, and internationalization support.
185204Flask App Builder is provided under the
186205[BSD 3 - Clause " New" or " Revised" license ](https:// github.com/ dpgaspar/ Flask- AppBuilder/ blob/ master/ LICENSE ).
187206
188- [ ** Flask AppBuilder / flask_appbuilder / tests / _ test_oauth_registration_role .py** ] ( https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/tests/_test_oauth_registration_role .py )
207+ [** Flask AppBuilder / flask_appbuilder / tests / test_mongoengine .py** ](https:// github.com/ dpgaspar/ Flask- AppBuilder/ blob/ master/ flask_appbuilder/ tests/ test_mongoengine .py)
189208
190209```python
191- # _test_oauth_registration_role.py
192- import logging
193- import unittest
194-
195- ~~ from flask import Flask
196- from flask_appbuilder import AppBuilder, SQLA
210+ # test_mongoengine.py
211+ from flask_appbuilder.views import CompactCRUDMixin, MasterDetailView
212+ from flask_mongoengine import MongoEngine
213+ import jinja2
214+ from nose.tools import eq_, ok_
197215
216+ from .base import FABTestCase
217+ from .mongoengine.models import Model1, Model2
198218
199219logging.basicConfig(format = " %(asctime)s :%(levelname)s :%(name)s :%(message)s " )
200220logging.getLogger().setLevel(logging.DEBUG )
201- log = logging.getLogger(__name__ )
202-
203-
204- class OAuthRegistrationRoleTestCase (unittest .TestCase ):
205- def setUp (self ):
206- ~~ self .app = Flask(__name__ )
207- self .app.config[" SQLALCHEMY_TRACK_MODIFICATIONS" ] = False
208- self .db = SQLA(self .app)
209221
210- def tearDown (self ):
211- self .appbuilder = None
212- self .app = None
213- self .db = None
214222
215- def test_self_registration_not_enabled (self ):
216- self .app.config[" AUTH_USER_REGISTRATION" ] = False
217- self .appbuilder = AppBuilder(self .app, self .db.session)
223+ DEFAULT_INDEX_STRING = " Welcome"
224+ INVALID_LOGIN_STRING = " Invalid login"
225+ ACCESS_IS_DENIED = " Access is Denied"
226+ UNIQUE_VALIDATION_STRING = " Already exists"
227+ NOTNULL_VALIDATION_STRING = " This field is required"
228+ DEFAULT_ADMIN_USER = " admin"
229+ DEFAULT_ADMIN_PASSWORD = " general"
218230
219- result = self .appbuilder.sm.auth_user_oauth(userinfo = {" username" : " testuser" })
220-
221- self .assertIsNone(result)
222- self .assertEqual(len (self .appbuilder.sm.get_all_users()), 0 )
231+ log = logging.getLogger(__name__ )
223232
224- def test_register_and_attach_static_role (self ):
225- self .app.config[" AUTH_USER_REGISTRATION" ] = True
226- self .app.config[" AUTH_USER_REGISTRATION_ROLE" ] = " Public"
227- self .appbuilder = AppBuilder(self .app, self .db.session)
228233
229- user = self .appbuilder.sm.auth_user_oauth(userinfo = {" username" : " testuser" })
234+ class FlaskTestCase(FABTestCase):
235+ def setUp(self ):
236+ ~~ from flask import Flask
237+ from flask_appbuilder import AppBuilder
238+ from flask_appbuilder.models.mongoengine.interface import MongoEngineInterface
239+ from flask_appbuilder import ModelView
240+ from flask_appbuilder.security.mongoengine.manager import SecurityManager
230241
242+ ~~ self .app = Flask(__name__ )
243+ self .app.jinja_env.undefined = jinja2.StrictUndefined
244+ self .basedir = os.path.abspath(os.path.dirname(__file__ ))
245+ self .app.config[" MONGODB_SETTINGS" ] = {" DB" : " test" }
246+ self .app.config[" CSRF_ENABLED" ] = False
247+ self .app.config[" SECRET_KEY" ] = " thisismyscretkey"
248+ self .app.config[" WTF_CSRF_ENABLED" ] = False
249+
250+ self .db = MongoEngine(self .app)
251+ self .appbuilder = AppBuilder(self .app, security_manager_class = SecurityManager)
252+
253+ class Model2View(ModelView):
254+ datamodel = MongoEngineInterface(Model2)
255+ list_columns = [
256+ " field_integer" ,
257+ " field_float" ,
258+ " field_string" ,
259+ " field_method" ,
260+ " group.field_string" ,
261+ ]
262+ edit_form_query_rel_fields = {
263+ " group" : [[" field_string" , FilterEqual, " G2" ]]
264+ }
265+ add_form_query_rel_fields = {" group" : [[" field_string" , FilterEqual, " G1" ]]}
266+ add_exclude_columns = [" excluded_string" ]
231267
232268
233269# # ... source file continues with no further Flask examples...
@@ -1316,7 +1352,80 @@ def create_celery_app():
13161352```
13171353
13181354
1319- ## Example 20 from tedivms-flask
1355+ # # Example 20 from ShortMe
1356+ [ShortMe](https:// github.com/ AcrobaticPanicc/ ShortMe- URL - Shortener)
1357+ is a [Flask](/ flask.html) app that creates a shortened URL
1358+ that redirects to another, typically much longer, URL . The
1359+ project is provided as open source under the
1360+ [MIT license ](https:// github.com/ AcrobaticPanicc/ ShortMe- URL - Shortener/ blob/ main/ LICENSE ).
1361+
1362+ [** ShortMe / app / setup.py** ](https:// github.com/ AcrobaticPanicc/ ShortMe- URL - Shortener/ blob/ main/ app/ ./ setup.py)
1363+
1364+ ```python
1365+ # setup.py
1366+ import os
1367+
1368+ ~~ from flask import Flask
1369+ from flask_restful import Api
1370+ from dotenv import load_dotenv
1371+
1372+ from app.db.extensions import db
1373+ from app.db.models import AuthToken
1374+ from app.views.index.index import index_blueprint
1375+ from app.views.internal.redirect_to_url import redirect_to_url_blueprint
1376+ from app.views.internal.favicon import app_blueprint
1377+ from app.views.internal.send_verification_code import send_otp_blueprint
1378+ from app.views.internal.shorten_url import shorten_url_blueprint
1379+ from app.views.your_short_url.your_short_url import your_short_url_blueprint
1380+ from app.views.total_clicks.total_clicks import total_clicks_blueprint
1381+ from app.views.error.error import error_blueprint
1382+ from app.views.page_not_found.page_not_found import page_not_found_blueprint
1383+ from app.views.api_doc.api_doc import api_doc_blueprint
1384+ from app.views.get_token.get_token import get_token_blueprint
1385+ from app.views.your_api_token.your_api_token import your_api_token_blueprint
1386+ from app.views.verify_code.verify_code import verify_code_blueprint
1387+
1388+ from app.api.api import Shorten, TotalClicks, GetToken
1389+
1390+
1391+ def create_app(config_file):
1392+ app_path = os.path.dirname(os.path.abspath(__file__ ))
1393+ project_folder = os.path.expanduser(app_path)
1394+ load_dotenv(os.path.join(project_folder, ' .env' ))
1395+
1396+ ~~ app = Flask(__name__ )
1397+ api = Api(app)
1398+ app.config.from_pyfile(config_file)
1399+
1400+ db.init_app(app)
1401+
1402+ with app.app_context():
1403+ db.drop_all()
1404+ db.create_all()
1405+
1406+ app_auth_token = app.secret_key
1407+ auth_token = AuthToken(auth_token = app_auth_token)
1408+ db.session.add(auth_token)
1409+ db.session.commit()
1410+
1411+ api.add_resource(Shorten, ' /api/shorten' )
1412+ api.add_resource(GetToken, ' /api/get_token' )
1413+ api.add_resource(TotalClicks, ' /api/total_clicks' )
1414+
1415+ app.register_blueprint(index_blueprint)
1416+ app.register_blueprint(page_not_found_blueprint)
1417+ app.register_blueprint(redirect_to_url_blueprint)
1418+ app.register_blueprint(your_short_url_blueprint)
1419+ app.register_blueprint(total_clicks_blueprint)
1420+ app.register_blueprint(error_blueprint)
1421+
1422+
1423+ # # ... source file continues with no further Flask examples...
1424+
1425+ ```
1426+
1427+
1428+ # # Example 21 from tedivms-flask
13201429[tedivm' s flask starter app](https://github.com/tedivm/tedivms-flask) is a
13211430base of [Flask](/ flask.html) code and related projects such as
13221431[Celery](/ celery.html) which provides a template to start your own
@@ -1339,7 +1448,8 @@ import os
13391448import requests
13401449import yaml
13411450
1342- ~~ from flask import Flask, session, render_template
1451+ ~~ from flask import Flask, render_template
1452+ from flask import session as current_session
13431453from flask_mail import Mail
13441454from flask_migrate import Migrate, MigrateCommand
13451455from flask.sessions import SessionInterface
@@ -1445,7 +1555,7 @@ def create_app(extra_config_settings={}):
14451555```
14461556
14471557
1448- ## Example 21 from trape
1558+ # # Example 22 from trape
14491559[trape](https:// github.com/ jofpin/ trape) is a research tool for tracking
14501560people' s activities that are logged digitally. The tool uses
14511561[Flask](/ flask.html) to create a web front end to view aggregated data
0 commit comments