feat: add recaptcha support
This commit is contained in:
		| @@ -204,19 +204,23 @@ def register_settings(app): | ||||
|     # Load environment specific settings | ||||
|     app.config['TESTING'] = False | ||||
|     app.config['DEBUG'] = False | ||||
|     app.config['SQLALCHEMY_ENGINE_OPTIONS'] = { | ||||
|         "pool_pre_ping": True, | ||||
|         "pool_size": 10, | ||||
|         "max_overflow": 2, | ||||
|         "pool_recycle": 300, | ||||
|         "pool_pre_ping": True, | ||||
|         "pool_use_lifo": True | ||||
|     } | ||||
|  | ||||
|     # always pull these two from the env | ||||
|     app.config['SECRET_KEY'] = os.getenv( | ||||
|         'APP_SECRET_KEY', | ||||
|         app.config['APP_SECRET_KEY'] | ||||
|  | ||||
|     ) | ||||
|     app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv( | ||||
|         'APP_DATABASE_URI', | ||||
|         app.config['APP_DATABASE_URI'] | ||||
|     ) | ||||
|  | ||||
|     # try to get overides, otherwise just use what we have already | ||||
|     app.config['USER_ENABLE_REGISTER'] = os.getenv( | ||||
|         'USER_ENABLE_REGISTER', | ||||
|         app.config['USER_ENABLE_REGISTER'] | ||||
| @@ -241,14 +245,6 @@ def register_settings(app): | ||||
|         'USER_REQUIRE_INVITATION', | ||||
|         app.config['USER_REQUIRE_INVITATION'] | ||||
|     ) | ||||
|     app.config['SQLALCHEMY_ENGINE_OPTIONS'] = { | ||||
|         "pool_pre_ping": True, | ||||
|         "pool_size": 10, | ||||
|         "max_overflow": 2, | ||||
|         "pool_recycle": 300, | ||||
|         "pool_pre_ping": True, | ||||
|         "pool_use_lifo": True | ||||
|     } | ||||
|     app.config['MAIL_SERVER'] = os.getenv( | ||||
|         'MAIL_SERVER', | ||||
|         app.config['MAIL_SERVER'] | ||||
| @@ -312,6 +308,41 @@ def register_settings(app): | ||||
|         app.config['CACHE_LOCATION'] | ||||
|     ) | ||||
|  | ||||
|     # Recaptcha settings | ||||
|     if "RECAPTCHA_ENABLE" not in app.config: | ||||
|         app.config['RECAPTCHA_ENABLE'] = False | ||||
|     app.config['RECAPTCHA_ENABLE'] = os.getenv( | ||||
|         'RECAPTCHA_ENABLE', | ||||
|         app.config['RECAPTCHA_ENABLE'] | ||||
|     ) | ||||
|     if "RECAPTCHA_PUBLIC_KEY" not in app.config: | ||||
|         app.config['RECAPTCHA_PUBLIC_KEY'] = '' | ||||
|     app.config['RECAPTCHA_PUBLIC_KEY'] = os.getenv( | ||||
|         'RECAPTCHA_PUBLIC_KEY', | ||||
|         app.config['RECAPTCHA_PUBLIC_KEY'] | ||||
|     ) | ||||
|     if "RECAPTCHA_PRIVATE_KEY" not in app.config: | ||||
|         app.config['RECAPTCHA_PRIVATE_KEY'] = '' | ||||
|     app.config['RECAPTCHA_PRIVATE_KEY'] = os.getenv( | ||||
|         'RECAPTCHA_PRIVATE_KEY', | ||||
|         app.config['RECAPTCHA_PRIVATE_KEY'] | ||||
|     ) | ||||
|     # Optional | ||||
|     app.config['RECAPTCHA_API_SERVER'] = os.getenv( | ||||
|         'RECAPTCHA_API_SERVER', | ||||
|         app.config['RECAPTCHA_API_SERVER'] | ||||
|     ) | ||||
|     app.config['RECAPTCHA_PARAMETERS'] = os.getenv( | ||||
|         'RECAPTCHA_PARAMETERS', | ||||
|         app.config['RECAPTCHA_PARAMETERS'] | ||||
|     ) | ||||
|     if "RECAPTCHA_DATA_ATTRS" not in app.config: | ||||
|         app.config['RECAPTCHA_DATA_ATTRS'] = {'theme': 'white', 'size': 'invisible'} | ||||
|     app.config['RECAPTCHA_DATA_ATTRS'] = os.getenv( | ||||
|         'RECAPTCHA_DATA_ATTRS', | ||||
|         app.config['RECAPTCHA_DATA_ATTRS'] | ||||
|     ) | ||||
|  | ||||
|  | ||||
|  | ||||
| def gm_level(gm_level): | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| from flask_wtf import FlaskForm | ||||
| from flask_wtf.recaptcha import RecaptchaField | ||||
| from flask import current_app | ||||
|  | ||||
| from flask_user.forms import ( | ||||
| @@ -84,6 +85,10 @@ class CustomRegisterForm(FlaskForm): | ||||
|     ]) | ||||
|  | ||||
|     invite_token = HiddenField('Token') | ||||
|      | ||||
|     # Use recaptcha if config enables recaptcha | ||||
|     if current_app.config["ENABLE_RECAPTCHA"]: | ||||
|         recaptcha = RecaptchaField() | ||||
|  | ||||
|     submit = SubmitField('Register') | ||||
|  | ||||
|   | ||||
| @@ -61,3 +61,13 @@ USER_AFTER_LOGOUT_ENDPOINT = "main.index" | ||||
|  | ||||
| # Option will be removed once this feature is full implemeted | ||||
| ENABLE_CHAR_XML_UPLOAD = False | ||||
|  | ||||
| # Recaptcha settings | ||||
| # See: https://flask-wtf.readthedocs.io/en/1.2.x/form/#recaptcha | ||||
| RECAPTCHA_ENABLE = False | ||||
| RECAPTCHA_PUBLIC_KEY = '' | ||||
| RECAPTCHA_PRIVATE_KEY = '' | ||||
| # Optional | ||||
| # RECAPTCHA_API_SERVER = '' | ||||
| # RECAPTCHA_PARAMETERS = '' | ||||
| RECAPTCHA_DATA_ATTRS = {'theme': 'white', 'size': 'invisible'} | ||||
|   | ||||
| @@ -1,188 +0,0 @@ | ||||
| {% extends "bootstrap/base.html" %} | ||||
| {% block title %}Key Creation{% endblock %} | ||||
|  | ||||
| {% block navbar %} | ||||
| <nav class="navbar navbar-default"> | ||||
|   <div class="container-fluid"> | ||||
|     <div class="navbar-header"> | ||||
|       <a class="navbar-brand" href="{{ url_for('dashboard') }}">Dashboard</a> | ||||
|     </div> | ||||
|     <ul class="nav navbar-nav"> | ||||
|     </ul> | ||||
|     <ul class="nav navbar-nav" style="float: right"> | ||||
|       <li class="active"><a href="#">Welcome {{ current_user.username }}!</a></li> | ||||
|       <li><a href="{{ url_for('logout') }}">Logout</a></li> | ||||
|     </ul> | ||||
|   </div> | ||||
| </nav> | ||||
| {% endblock navbar %}} | ||||
|  | ||||
| {% block content %} | ||||
| {# LOGO #} | ||||
| <div class="container" style="margin-top: 50px"> | ||||
|  | ||||
|     {# Display logo #} | ||||
|     <div style="margin-bottom: 50px"> | ||||
|         <img | ||||
|                 src="{{ url_for('static', filename=resources.LOGO) }}" | ||||
|                 class="center-block img-responsive mx-auto d-block" | ||||
|                 alt="Logo" | ||||
|                 width="100" | ||||
|                 height="100" | ||||
|         > | ||||
|     </div> | ||||
|  | ||||
| </div> | ||||
|  | ||||
| {# Key creation #} | ||||
| <div class="container"> | ||||
|     <div class="text-center"> | ||||
|         <h3>Key Creation</h3> | ||||
|     </div> | ||||
|  | ||||
|     <div class="col-lg-3"> | ||||
|     </div> | ||||
|     <div class="col-lg-6"> | ||||
|  | ||||
|     {# If the error value is set, display the error in red text #} | ||||
|     {% if error %} | ||||
|         <div class="alert alert-danger"> | ||||
|             {{ error }} | ||||
|         </div> | ||||
|     {% endif %} | ||||
|  | ||||
|     {# If the message value is set, display the message in green text #} | ||||
|     {% if message %} | ||||
|         <div class="alert alert-success"> | ||||
|             {{ message }} | ||||
|         </div> | ||||
|     {% endif %} | ||||
|  | ||||
|     {# Form which takes in Admin Username, Admin Password, and the amount of keys to create. #} | ||||
|     <form action="{{ url_for('dashboard') }}" method="post"> | ||||
|         {# Key count input #} | ||||
|         <div class="form-group"> | ||||
|             <label for="key_count">Generate keys</label> | ||||
|             <input type="number" class="form-control" name="key_count" placeholder="Enter number of keys..."> | ||||
|             <small class="form-text text-muted">Number of keys to create.</small> | ||||
|         </div> | ||||
|          | ||||
|         {# Submit button #} | ||||
|         <div class="form-group"> | ||||
|             <button type="submit" class="btn btn-primary">Generate Keys</button> | ||||
|         </div> | ||||
|     </form> | ||||
|  | ||||
|     {# If the keys value is set, create a list for each key in keys #} | ||||
|     {% if keys %} | ||||
|         <div class="alert alert-success"> | ||||
|             <ul> | ||||
|                 {% for key in keys %} | ||||
|                     <li>{{ key }}</li> | ||||
|                 {% endfor %} | ||||
|             </ul> | ||||
|         </div> | ||||
|     {% endif %} | ||||
|     </div> | ||||
|     <div class="col-lg-3"> | ||||
|     </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| {# Activity graphs #} | ||||
| <div class="container"> | ||||
|  | ||||
|     <div class="text-center"> | ||||
|         <h3>Activity</h3> | ||||
|     </div> | ||||
|  | ||||
|     <div class="col-lg-3"> | ||||
|     </div> | ||||
|  | ||||
|     <div class="col-lg-6"> | ||||
|  | ||||
|     <canvas id="sessions_graph" width="400" height="400"></canvas> | ||||
|     <canvas id="play_time_graph" width="400" height="400"></canvas> | ||||
|     <canvas id="zone_play_time_graph" width="400" height="400"></canvas> | ||||
|  | ||||
|     </div> | ||||
|  | ||||
|     <div class="col-lg-3"> | ||||
|     </div> | ||||
| </div> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block scripts %} | ||||
| <script src="https://cdn.jsdelivr.net/npm/chart.js@3.5.1/dist/chart.min.js"></script> | ||||
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> | ||||
|  | ||||
| <script> | ||||
| // Make a get request to the server to load the activity data | ||||
| $.get("{{ url_for('load_activities') }}", function(data) { | ||||
|  | ||||
| }); | ||||
|  | ||||
| // Make a get request to the server to get the activity data for "sessions" | ||||
| $.get("{{ url_for('activity_data', name='sessions') }}", function(data) { | ||||
|     // Load data as a json object | ||||
|     data = JSON.parse(data); | ||||
|     var ctx = document.getElementById('sessions_graph').getContext('2d'); | ||||
|     var myChart = new Chart(ctx, { | ||||
|         type: 'line', | ||||
|         data: { | ||||
|             labels: data.labels, | ||||
|             datasets: data.datasets | ||||
|         }, | ||||
|         options: { | ||||
|             scales: { | ||||
|                 y: { | ||||
|                     beginAtZero: true | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| // Make a get request to the server to get the activity data for "play_time" | ||||
| $.get("{{ url_for('activity_data', name='play_time') }}", function(data) { | ||||
|     // Load data as a json object | ||||
|     data = JSON.parse(data); | ||||
|     var ctx = document.getElementById('play_time_graph').getContext('2d'); | ||||
|     var myChart = new Chart(ctx, { | ||||
|         type: 'line', | ||||
|         data: { | ||||
|             labels: data.labels, | ||||
|             datasets: data.datasets | ||||
|         }, | ||||
|         options: { | ||||
|             scales: { | ||||
|                 y: { | ||||
|                     beginAtZero: true | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| // Make a get request to the server to get the activity data for "zone_play_time" | ||||
| $.get("{{ url_for('activity_data', name='zone_play_time') }}", function(data) { | ||||
|     // Load data as a json object | ||||
|     data = JSON.parse(data); | ||||
|     var ctx = document.getElementById('zone_play_time_graph').getContext('2d'); | ||||
|     var myChart = new Chart(ctx, { | ||||
|         type: 'line', | ||||
|         data: { | ||||
|             labels: data.labels, | ||||
|             datasets: data.datasets | ||||
|         }, | ||||
|         options: { | ||||
|             scales: { | ||||
|                 y: { | ||||
|                     beginAtZero: true | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
| </script> | ||||
| {% endblock scripts %}} | ||||
| @@ -82,7 +82,6 @@ | ||||
|         </div> | ||||
|       {% endif %} | ||||
|  | ||||
|  | ||||
|       <div class="row"> | ||||
|         <div class="col text-right"> | ||||
|           Source | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 aronwk-aaron
					aronwk-aaron