API - remove intermediate directory and rename api directory
This commit is contained in:
0
fittrackee/application/__init__.py
Normal file
0
fittrackee/application/__init__.py
Normal file
171
fittrackee/application/app_config.py
Normal file
171
fittrackee/application/app_config.py
Normal file
@ -0,0 +1,171 @@
|
||||
from fittrackee import appLog, db
|
||||
from flask import Blueprint, current_app, jsonify, request
|
||||
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
||||
|
||||
from ..users.utils import authenticate_as_admin
|
||||
from .models import AppConfig
|
||||
from .utils import update_app_config_from_database
|
||||
|
||||
config_blueprint = Blueprint('config', __name__)
|
||||
|
||||
|
||||
@config_blueprint.route('/config', methods=['GET'])
|
||||
def get_application_config():
|
||||
"""
|
||||
Get Application config
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/config HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"gpx_limit_import": 10,
|
||||
"is_registration_enabled": false,
|
||||
"max_single_file_size": 1048576,
|
||||
"max_zip_file_size": 10485760,
|
||||
"max_users": 0
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
:statuscode 200: success
|
||||
:statuscode 500: Error on getting configuration.
|
||||
"""
|
||||
|
||||
try:
|
||||
config = AppConfig.query.one()
|
||||
response_object = {'status': 'success', 'data': config.serialize()}
|
||||
return jsonify(response_object), 200
|
||||
except (MultipleResultsFound, NoResultFound) as e:
|
||||
appLog.error(e)
|
||||
response_object = {
|
||||
'status': 'error',
|
||||
'message': 'Error on getting configuration.',
|
||||
}
|
||||
return jsonify(response_object), 500
|
||||
|
||||
|
||||
@config_blueprint.route('/config', methods=['PATCH'])
|
||||
@authenticate_as_admin
|
||||
def update_application_config(auth_user_id):
|
||||
"""
|
||||
Update Application config
|
||||
|
||||
Authenticated user must be an admin
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/config HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"gpx_limit_import": 10,
|
||||
"is_registration_enabled": true,
|
||||
"max_single_file_size": 1048576,
|
||||
"max_zip_file_size": 10485760,
|
||||
"max_users": 10
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
:param integer auth_user_id: authenticate user id (from JSON Web Token)
|
||||
|
||||
:<json integrer gpx_limit_import: max number of files in zip archive
|
||||
:<json boolean is_registration_enabled: is registration enabled ?
|
||||
:<json integrer max_single_file_size: max size of a single file
|
||||
:<json integrer max_zip_file_size: max size of a zip archive
|
||||
:<json integrer max_users: max users allowed to register on instance
|
||||
|
||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||
|
||||
:statuscode 200: success
|
||||
:statuscode 400: invalid payload
|
||||
:statuscode 401:
|
||||
- Provide a valid auth token.
|
||||
- Signature expired. Please log in again.
|
||||
- Invalid token. Please log in again.
|
||||
:statuscode 403: You do not have permissions.
|
||||
:statuscode 500: Error on updating configuration.
|
||||
"""
|
||||
config_data = request.get_json()
|
||||
if not config_data:
|
||||
response_object = {'status': 'error', 'message': 'Invalid payload.'}
|
||||
return jsonify(response_object), 400
|
||||
|
||||
try:
|
||||
config = AppConfig.query.one()
|
||||
if 'gpx_limit_import' in config_data:
|
||||
config.gpx_limit_import = config_data.get('gpx_limit_import')
|
||||
if 'max_single_file_size' in config_data:
|
||||
config.max_single_file_size = config_data.get(
|
||||
'max_single_file_size'
|
||||
)
|
||||
if 'max_zip_file_size' in config_data:
|
||||
config.max_zip_file_size = config_data.get('max_zip_file_size')
|
||||
if 'max_users' in config_data:
|
||||
config.max_users = config_data.get('max_users')
|
||||
|
||||
db.session.commit()
|
||||
update_app_config_from_database(current_app, config)
|
||||
|
||||
response_object = {'status': 'success', 'data': config.serialize()}
|
||||
code = 200
|
||||
|
||||
except Exception as e:
|
||||
appLog.error(e)
|
||||
response_object = {
|
||||
'status': 'error',
|
||||
'message': 'Error on updating configuration.',
|
||||
}
|
||||
code = 500
|
||||
return jsonify(response_object), code
|
||||
|
||||
|
||||
@config_blueprint.route('/ping', methods=['GET'])
|
||||
def health_check():
|
||||
"""health check endpoint
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/ping HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"message": "pong!",
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
:statuscode 200: success
|
||||
|
||||
"""
|
||||
return jsonify({'status': 'success', 'message': 'pong!'})
|
57
fittrackee/application/models.py
Normal file
57
fittrackee/application/models.py
Normal file
@ -0,0 +1,57 @@
|
||||
from fittrackee import db
|
||||
from flask import current_app
|
||||
from sqlalchemy.event import listens_for
|
||||
|
||||
from ..users.models import User
|
||||
|
||||
|
||||
class AppConfig(db.Model):
|
||||
__tablename__ = 'app_config'
|
||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
max_users = db.Column(db.Integer, default=0, nullable=False)
|
||||
gpx_limit_import = db.Column(db.Integer, default=10, nullable=False)
|
||||
max_single_file_size = db.Column(
|
||||
db.Integer, default=1048576, nullable=False
|
||||
)
|
||||
max_zip_file_size = db.Column(db.Integer, default=10485760, nullable=False)
|
||||
|
||||
@property
|
||||
def is_registration_enabled(self):
|
||||
nb_users = User.query.count()
|
||||
return self.max_users == 0 or nb_users < self.max_users
|
||||
|
||||
@property
|
||||
def map_attribution(self):
|
||||
return current_app.config['TILE_SERVER']['ATTRIBUTION']
|
||||
|
||||
def serialize(self):
|
||||
return {
|
||||
"gpx_limit_import": self.gpx_limit_import,
|
||||
"is_registration_enabled": self.is_registration_enabled,
|
||||
"max_single_file_size": self.max_single_file_size,
|
||||
"max_zip_file_size": self.max_zip_file_size,
|
||||
"max_users": self.max_users,
|
||||
"map_attribution": self.map_attribution,
|
||||
}
|
||||
|
||||
|
||||
def update_app_config():
|
||||
config = AppConfig.query.first()
|
||||
if config:
|
||||
current_app.config[
|
||||
'is_registration_enabled'
|
||||
] = config.is_registration_enabled
|
||||
|
||||
|
||||
@listens_for(User, 'after_insert')
|
||||
def on_user_insert(mapper, connection, user):
|
||||
@listens_for(db.Session, 'after_flush', once=True)
|
||||
def receive_after_flush(session, context):
|
||||
update_app_config()
|
||||
|
||||
|
||||
@listens_for(User, 'after_delete')
|
||||
def on_user_delete(mapper, connection, old_user):
|
||||
@listens_for(db.Session, 'after_flush', once=True)
|
||||
def receive_after_flush(session, context):
|
||||
update_app_config()
|
46
fittrackee/application/utils.py
Normal file
46
fittrackee/application/utils.py
Normal file
@ -0,0 +1,46 @@
|
||||
import os
|
||||
|
||||
from fittrackee import db
|
||||
from fittrackee.users.models import User
|
||||
|
||||
from .models import AppConfig
|
||||
|
||||
MAX_FILE_SIZE = 1 * 1024 * 1024 # 1MB
|
||||
|
||||
|
||||
def init_config():
|
||||
"""
|
||||
init application configuration if not existing in database
|
||||
|
||||
Note: get some configuration values from env variables
|
||||
(for FitTrackee versions prior to v0.3.0)
|
||||
"""
|
||||
existing_config = AppConfig.query.one_or_none()
|
||||
nb_users = User.query.count()
|
||||
if not existing_config:
|
||||
config = AppConfig()
|
||||
config.max_users = (
|
||||
nb_users
|
||||
if os.getenv('REACT_APP_ALLOW_REGISTRATION') == "false"
|
||||
else 0
|
||||
)
|
||||
config.max_single_file_size = os.environ.get(
|
||||
'REACT_APP_MAX_SINGLE_FILE_SIZE', MAX_FILE_SIZE
|
||||
)
|
||||
config.max_zip_file_size = os.environ.get(
|
||||
'REACT_APP_MAX_ZIP_FILE_SIZE', MAX_FILE_SIZE * 10
|
||||
)
|
||||
db.session.add(config)
|
||||
db.session.commit()
|
||||
return True, config
|
||||
return False, existing_config
|
||||
|
||||
|
||||
def update_app_config_from_database(current_app, db_config):
|
||||
current_app.config['gpx_limit_import'] = db_config.gpx_limit_import
|
||||
current_app.config['max_single_file_size'] = db_config.max_single_file_size
|
||||
current_app.config['MAX_CONTENT_LENGTH'] = db_config.max_zip_file_size
|
||||
current_app.config['max_users'] = db_config.max_users
|
||||
current_app.config[
|
||||
'is_registration_enabled'
|
||||
] = db_config.is_registration_enabled
|
Reference in New Issue
Block a user