├── .env ├── .gitignore ├── README.md ├── config.py ├── index.py ├── preview1.png ├── preview2.png ├── requirements.txt ├── scripts ├── flask_jwt_backup.sql └── stored_procedures.sql └── src ├── __init__.py ├── database ├── __init__.py └── db_mysql.py ├── models ├── LanguageModel.py ├── UserModel.py └── __init__.py ├── routes ├── AuthRoutes.py ├── IndexRoutes.py ├── LanguageRoutes.py └── __init__.py ├── services ├── AuthService.py ├── LanguageService.py └── __init__.py ├── tests ├── __init__.py └── services │ ├── __init__.py │ └── test_LanguageService.py └── utils ├── Logger.py ├── Security.py └── log └── app.log /.env: -------------------------------------------------------------------------------- 1 | SECRET_KEY=B!1w8*NAt1T^%kvhUI*S^_ 2 | 3 | MYSQL_HOST=localhost 4 | MYSQL_USER=root 5 | MYSQL_PASSWORD=123456 6 | MYSQL_DB=flask_jwt 7 | 8 | JWT_KEY=D5*F?_1?-d$f*1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv/ 2 | 3 | __pycache__/ 4 | *.py[cod] 5 | 6 | .pytest_cache/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python & Flask: Estructura de Carpetas y Archivos 2 | 3 | Aprende a estructurar un proyecto web (RESTful API) de Python y Flask organizando tus archivos y carpetas de forma ordenada, incluyendo directorios para: routes, models, services, testing y más. 4 | 5 |
6 | 7 | Primero, crear un entorno virtual: 8 | ### `python -m virtualenv venv` 9 | 10 | Para instalar los paquetes necesarios: 11 | ### `pip install -r requirements.txt` 12 | 13 |
14 | 15 | ![](./preview1.png) 16 |

17 | ![](./preview2.png) 18 | 19 | # 🌍 Por si deseas contactarme 👨‍💻 : 20 | 21 | [![LinkedIn](https://img.shields.io/badge/LinkedIn-Oscar_Garcia-0077B5?style=for-the-badge&logo=linkedin&logoColor=white&labelColor=101010)](https://pe.linkedin.com/in/uskokrum2010) 22 | [![YouTube](https://img.shields.io/badge/YouTube-UskoKruM2010-FF0000?style=for-the-badge&logo=youtube&logoColor=white&labelColor=101010)](https://youtube.com/uskokrum2010) 23 | [![Twitter](https://img.shields.io/badge/Twitter-@uskokrum2010-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white&labelColor=101010)](https://twitter.com/uskokrum2010) 24 | [![Instagram](https://img.shields.io/badge/Instagram-@uskokrum2010-E4405F?style=for-the-badge&logo=instagram&logoColor=white&labelColor=101010)](https://instagram.com/uskokrum2010) 25 | [![Facebook](https://img.shields.io/badge/Facebook-@uskokrum2010-1877F2?style=for-the-badge&logo=facebook&logoColor=white&labelColor=101010)](https://facebook.com/uskokrum2010) 26 | [![Udemy](https://img.shields.io/badge/Udemy-Oscar_Garcia-EC5252?style=for-the-badge&logo=udemy&logoColor=white&labelColor=101010)](https://www.udemy.com/course/sql-para-administracion-de-bases-de-datos-con-mysql/) 27 | [![Web](https://img.shields.io/badge/My_Website-uskokrum2010.com-14a1f0?style=for-the-badge&logo=dev.to&logoColor=white&labelColor=101010)](https://uskokrum2010.com) 28 | [![Email](https://img.shields.io/badge/uskokrum2010@gmail.com-mi_email_personal-D14836?style=for-the-badge&logo=gmail&logoColor=white&labelColor=101010)](mailto:uskokrum2010@gmail.com) -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | from decouple import config 2 | 3 | 4 | class Config(): 5 | SECRET_KEY = config('SECRET_KEY') 6 | 7 | 8 | class DevelopmentConfig(Config): 9 | DEBUG = True 10 | 11 | 12 | config = { 13 | 'development': DevelopmentConfig 14 | } 15 | -------------------------------------------------------------------------------- /index.py: -------------------------------------------------------------------------------- 1 | from config import config 2 | from src import init_app 3 | 4 | configuration = config['development'] 5 | app = init_app(configuration) 6 | 7 | if __name__ == '__main__': 8 | app.run() 9 | -------------------------------------------------------------------------------- /preview1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/preview1.png -------------------------------------------------------------------------------- /preview2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/preview2.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/requirements.txt -------------------------------------------------------------------------------- /scripts/flask_jwt_backup.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 5.1.1 3 | -- https://www.phpmyadmin.net/ 4 | -- 5 | -- Servidor: 127.0.0.1 6 | -- Tiempo de generación: 31-05-2023 a las 03:54:55 7 | -- Versión del servidor: 10.4.22-MariaDB 8 | -- Versión de PHP: 8.1.2 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | START TRANSACTION; 12 | SET time_zone = "+00:00"; 13 | 14 | 15 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 16 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 17 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 18 | /*!40101 SET NAMES utf8mb4 */; 19 | 20 | -- 21 | -- Base de datos: `flask_jwt` 22 | -- 23 | 24 | DELIMITER $$ 25 | -- 26 | -- Procedimientos 27 | -- 28 | CREATE PROCEDURE `sp_addUser` (IN `pUsername` VARCHAR(20), IN `pPassword` VARCHAR(20), IN `pFullname` VARCHAR(50)) BEGIN 29 | INSERT INTO user (username, password, fullname) 30 | VALUES (pUsername, AES_ENCRYPT(pPassword, SHA2('B!1w8*NAt1T^%kvhUI*S^_', 512)), pFullname); 31 | END$$ 32 | 33 | CREATE PROCEDURE `sp_listLanguages` () BEGIN 34 | SELECT LAN.id, LAN.name 35 | FROM language LAN 36 | ORDER BY LAN.name ASC; 37 | END$$ 38 | 39 | CREATE PROCEDURE `sp_verifyIdentity` (IN `pUsername` VARCHAR(20), IN `pPassword` VARCHAR(20)) BEGIN 40 | SELECT USER.id, USER.username, USER.fullname 41 | FROM user USER 42 | WHERE 1 = 1 43 | AND USER.username = pUsername 44 | AND CAST(AES_DECRYPT(USER.password, SHA2('B!1w8*NAt1T^%kvhUI*S^_', 512)) AS CHAR(30)) = pPassword; 45 | END$$ 46 | 47 | DELIMITER ; 48 | 49 | -- -------------------------------------------------------- 50 | 51 | -- 52 | -- Estructura de tabla para la tabla `language` 53 | -- 54 | 55 | CREATE TABLE `language` ( 56 | `id` tinyint(2) UNSIGNED NOT NULL, 57 | `name` varchar(20) COLLATE utf8_unicode_ci NOT NULL 58 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Store the languages data.'; 59 | 60 | -- 61 | -- Volcado de datos para la tabla `language` 62 | -- 63 | 64 | INSERT INTO `language` (`id`, `name`) VALUES 65 | (1, 'Python'), 66 | (2, 'Java'), 67 | (3, 'C#'), 68 | (4, 'PHP'), 69 | (5, 'JavaScript'), 70 | (6, 'Kotlin'); 71 | 72 | -- -------------------------------------------------------- 73 | 74 | -- 75 | -- Estructura de tabla para la tabla `user` 76 | -- 77 | 78 | CREATE TABLE `user` ( 79 | `id` smallint(3) UNSIGNED NOT NULL, 80 | `username` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 81 | `password` blob NOT NULL, 82 | `fullname` varchar(50) COLLATE utf8_unicode_ci NOT NULL 83 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Stores the user''s data.'; 84 | 85 | -- 86 | -- Volcado de datos para la tabla `user` 87 | -- 88 | 89 | INSERT INTO `user` (`id`, `username`, `password`, `fullname`) VALUES 90 | (1, 'USKOKRUM', 0x98fb67ca8f459f49841208bd4261bceb, 'Oscar García'); 91 | 92 | -- 93 | -- Índices para tablas volcadas 94 | -- 95 | 96 | -- 97 | -- Indices de la tabla `language` 98 | -- 99 | ALTER TABLE `language` 100 | ADD PRIMARY KEY (`id`); 101 | 102 | -- 103 | -- Indices de la tabla `user` 104 | -- 105 | ALTER TABLE `user` 106 | ADD PRIMARY KEY (`id`); 107 | 108 | -- 109 | -- AUTO_INCREMENT de las tablas volcadas 110 | -- 111 | 112 | -- 113 | -- AUTO_INCREMENT de la tabla `language` 114 | -- 115 | ALTER TABLE `language` 116 | MODIFY `id` tinyint(2) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; 117 | 118 | -- 119 | -- AUTO_INCREMENT de la tabla `user` 120 | -- 121 | ALTER TABLE `user` 122 | MODIFY `id` smallint(3) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; 123 | COMMIT; 124 | 125 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 126 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 127 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 128 | -------------------------------------------------------------------------------- /scripts/stored_procedures.sql: -------------------------------------------------------------------------------- 1 | -- Language 2 | DELIMITER // 3 | CREATE PROCEDURE sp_listLanguages() 4 | BEGIN 5 | SELECT LAN.id, LAN.name 6 | FROM language LAN 7 | ORDER BY LAN.name ASC; 8 | END // 9 | DELIMITER ; 10 | 11 | -- User 12 | DELIMITER // 13 | CREATE PROCEDURE sp_addUser(IN pUsername VARCHAR(20), IN pPassword VARCHAR(20), IN pFullname VARCHAR(50)) 14 | BEGIN 15 | INSERT INTO user (username, password, fullname) 16 | VALUES (pUsername, AES_ENCRYPT(pPassword, SHA2('B!1w8*NAt1T^%kvhUI*S^_', 512)), pFullname); 17 | END // 18 | DELIMITER ; 19 | 20 | DELIMITER // 21 | CREATE PROCEDURE sp_verifyIdentity(IN pUsername VARCHAR(20), IN pPassword VARCHAR(20)) 22 | BEGIN 23 | SELECT USER.id, USER.username, USER.fullname 24 | FROM user USER 25 | WHERE 1 = 1 26 | AND USER.username = pUsername 27 | AND CAST(AES_DECRYPT(USER.password, SHA2('B!1w8*NAt1T^%kvhUI*S^_', 512)) AS CHAR(30)) = pPassword; 28 | END // 29 | DELIMITER ; -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | # Routes 4 | from .routes import AuthRoutes, IndexRoutes, LanguageRoutes 5 | 6 | app = Flask(__name__) 7 | 8 | 9 | def init_app(config): 10 | # Configuration 11 | app.config.from_object(config) 12 | 13 | # Blueprints 14 | app.register_blueprint(IndexRoutes.main, url_prefix='/') 15 | app.register_blueprint(AuthRoutes.main, url_prefix='/auth') 16 | app.register_blueprint(LanguageRoutes.main, url_prefix='/languages') 17 | 18 | return app 19 | -------------------------------------------------------------------------------- /src/database/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/src/database/__init__.py -------------------------------------------------------------------------------- /src/database/db_mysql.py: -------------------------------------------------------------------------------- 1 | from decouple import config 2 | 3 | import pymysql 4 | import traceback 5 | 6 | # Logger 7 | from src.utils.Logger import Logger 8 | 9 | 10 | def get_connection(): 11 | try: 12 | return pymysql.connect( 13 | host=config('MYSQL_HOST'), 14 | user=config('MYSQL_USER'), 15 | password=config('MYSQL_PASSWORD'), 16 | db=config('MYSQL_DB') 17 | ) 18 | except Exception as ex: 19 | Logger.add_to_log("error", str(ex)) 20 | Logger.add_to_log("error", traceback.format_exc()) 21 | -------------------------------------------------------------------------------- /src/models/LanguageModel.py: -------------------------------------------------------------------------------- 1 | class Language(): 2 | 3 | def __init__(self, id, name) -> None: 4 | self.id = id 5 | self.name = name 6 | 7 | def to_json(self): 8 | return { 9 | 'id': self.id, 10 | 'name': self.name 11 | } 12 | -------------------------------------------------------------------------------- /src/models/UserModel.py: -------------------------------------------------------------------------------- 1 | class User(): 2 | 3 | def __init__(self, id, username, password, fullname) -> None: 4 | self.id = id 5 | self.username = username 6 | self.password = password 7 | self.fullname = fullname 8 | -------------------------------------------------------------------------------- /src/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/src/models/__init__.py -------------------------------------------------------------------------------- /src/routes/AuthRoutes.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, request, jsonify 2 | 3 | import traceback 4 | 5 | # Logger 6 | from src.utils.Logger import Logger 7 | # Models 8 | from src.models.UserModel import User 9 | # Security 10 | from src.utils.Security import Security 11 | # Services 12 | from src.services.AuthService import AuthService 13 | 14 | main = Blueprint('auth_blueprint', __name__) 15 | 16 | 17 | @main.route('/', methods=['POST']) 18 | def login(): 19 | try: 20 | username = request.json['username'] 21 | password = request.json['password'] 22 | 23 | _user = User(0, username, password, None) 24 | authenticated_user = AuthService.login_user(_user) 25 | 26 | if (authenticated_user != None): 27 | encoded_token = Security.generate_token(authenticated_user) 28 | return jsonify({'success': True, 'token': encoded_token}) 29 | else: 30 | response = jsonify({'message': 'Unauthorized'}) 31 | return response, 401 32 | except Exception as ex: 33 | Logger.add_to_log("error", str(ex)) 34 | Logger.add_to_log("error", traceback.format_exc()) 35 | 36 | return jsonify({'message': "ERROR", 'success': False}) 37 | -------------------------------------------------------------------------------- /src/routes/IndexRoutes.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, jsonify, request 2 | 3 | import traceback 4 | 5 | # Logger 6 | from src.utils.Logger import Logger 7 | 8 | main = Blueprint('index_blueprint', __name__) 9 | 10 | 11 | @main.route('/') 12 | def index(): 13 | try: 14 | Logger.add_to_log("info", "{} {}".format(request.method, request.path)) 15 | return "Ok" 16 | except Exception as ex: 17 | Logger.add_to_log("error", str(ex)) 18 | Logger.add_to_log("error", traceback.format_exc()) 19 | 20 | response = jsonify({'message': "Internal Server Error", 'success': False}) 21 | return response, 500 22 | -------------------------------------------------------------------------------- /src/routes/LanguageRoutes.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, request, jsonify 2 | 3 | import traceback 4 | 5 | # Logger 6 | from src.utils.Logger import Logger 7 | # Security 8 | from src.utils.Security import Security 9 | # Services 10 | from src.services.LanguageService import LanguageService 11 | 12 | main = Blueprint('language_blueprint', __name__) 13 | 14 | 15 | @main.route('/') 16 | def get_languages(): 17 | has_access = Security.verify_token(request.headers) 18 | 19 | if has_access: 20 | try: 21 | languages = LanguageService.get_languages() 22 | if (len(languages) > 0): 23 | return jsonify({'languages': languages, 'message': "SUCCESS", 'success': True}) 24 | else: 25 | return jsonify({'message': "NOTFOUND", 'success': True}) 26 | except Exception as ex: 27 | Logger.add_to_log("error", str(ex)) 28 | Logger.add_to_log("error", traceback.format_exc()) 29 | 30 | return jsonify({'message': "ERROR", 'success': False}) 31 | else: 32 | response = jsonify({'message': 'Unauthorized'}) 33 | return response, 401 34 | -------------------------------------------------------------------------------- /src/routes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/src/routes/__init__.py -------------------------------------------------------------------------------- /src/services/AuthService.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | 3 | # Database 4 | from src.database.db_mysql import get_connection 5 | # Logger 6 | from src.utils.Logger import Logger 7 | # Models 8 | from src.models.UserModel import User 9 | 10 | 11 | class AuthService(): 12 | 13 | @classmethod 14 | def login_user(cls, user): 15 | try: 16 | connection = get_connection() 17 | authenticated_user = None 18 | with connection.cursor() as cursor: 19 | cursor.execute('call sp_verifyIdentity(%s, %s)', (user.username, user.password)) 20 | row = cursor.fetchone() 21 | if row != None: 22 | authenticated_user = User(int(row[0]), row[1], None, row[2]) 23 | connection.close() 24 | return authenticated_user 25 | except Exception as ex: 26 | Logger.add_to_log("error", str(ex)) 27 | Logger.add_to_log("error", traceback.format_exc()) 28 | -------------------------------------------------------------------------------- /src/services/LanguageService.py: -------------------------------------------------------------------------------- 1 | import traceback 2 | 3 | # Database 4 | from src.database.db_mysql import get_connection 5 | # Logger 6 | from src.utils.Logger import Logger 7 | # Models 8 | from src.models.LanguageModel import Language 9 | 10 | 11 | class LanguageService(): 12 | 13 | @classmethod 14 | def get_languages(cls): 15 | try: 16 | connection = get_connection() 17 | languages = [] 18 | with connection.cursor() as cursor: 19 | cursor.execute('call sp_listLanguages()') 20 | resultset = cursor.fetchall() 21 | for row in resultset: 22 | language = Language(int(row[0]), row[1]) 23 | languages.append(language.to_json()) 24 | connection.close() 25 | return languages 26 | except Exception as ex: 27 | Logger.add_to_log("error", str(ex)) 28 | Logger.add_to_log("error", traceback.format_exc()) 29 | -------------------------------------------------------------------------------- /src/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/src/services/__init__.py -------------------------------------------------------------------------------- /src/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/src/tests/__init__.py -------------------------------------------------------------------------------- /src/tests/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/src/tests/services/__init__.py -------------------------------------------------------------------------------- /src/tests/services/test_LanguageService.py: -------------------------------------------------------------------------------- 1 | # Services 2 | from src.services.LanguageService import LanguageService 3 | 4 | 5 | def test_get_languages_not_none(): 6 | languages = LanguageService.get_languages() 7 | assert languages != None 8 | 9 | 10 | def test_get_languages_has_elements(): 11 | languages = LanguageService.get_languages() 12 | assert len(languages) > 0 13 | 14 | 15 | def test_get_languages_check_elements_length(): 16 | languages = LanguageService.get_languages() 17 | for language in languages: 18 | assert len(language) > 0 19 | -------------------------------------------------------------------------------- /src/utils/Logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import traceback 4 | 5 | 6 | class Logger(): 7 | 8 | def __set_logger(self): 9 | log_directory = 'src/utils/log' 10 | log_filename = 'app.log' 11 | 12 | logger = logging.getLogger(__name__) 13 | logger.setLevel(logging.DEBUG) 14 | 15 | log_path = os.path.join(log_directory, log_filename) 16 | file_handler = logging.FileHandler(log_path, encoding='utf-8') 17 | file_handler.setLevel(logging.DEBUG) 18 | 19 | formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s', "%Y-%m-%d %H:%M:%S") 20 | file_handler.setFormatter(formatter) 21 | 22 | if (logger.hasHandlers()): 23 | logger.handlers.clear() 24 | 25 | logger.addHandler(file_handler) 26 | 27 | return logger 28 | 29 | @classmethod 30 | def add_to_log(cls, level, message): 31 | try: 32 | logger = cls.__set_logger(cls) 33 | 34 | if (level == "critical"): 35 | logger.critical(message) 36 | elif (level == "debug"): 37 | logger.debug(message) 38 | elif (level == "error"): 39 | logger.error(message) 40 | elif (level == "info"): 41 | logger.info(message) 42 | elif (level == "warn"): 43 | logger.warn(message) 44 | except Exception as ex: 45 | print(traceback.format_exc()) 46 | print(ex) 47 | -------------------------------------------------------------------------------- /src/utils/Security.py: -------------------------------------------------------------------------------- 1 | from decouple import config 2 | 3 | import datetime 4 | import jwt 5 | import pytz 6 | import traceback 7 | 8 | # Logger 9 | from src.utils.Logger import Logger 10 | 11 | 12 | class Security(): 13 | 14 | secret = config('JWT_KEY') 15 | tz = pytz.timezone("America/Lima") 16 | 17 | @classmethod 18 | def generate_token(cls, authenticated_user): 19 | try: 20 | payload = { 21 | 'iat': datetime.datetime.now(tz=cls.tz), 22 | 'exp': datetime.datetime.now(tz=cls.tz) + datetime.timedelta(minutes=10), 23 | 'username': authenticated_user.username, 24 | 'fullname': authenticated_user.fullname, 25 | 'roles': ['Administrator', 'Editor'] 26 | } 27 | return jwt.encode(payload, cls.secret, algorithm="HS256") 28 | except Exception as ex: 29 | Logger.add_to_log("error", str(ex)) 30 | Logger.add_to_log("error", traceback.format_exc()) 31 | 32 | @classmethod 33 | def verify_token(cls, headers): 34 | try: 35 | if 'Authorization' in headers.keys(): 36 | authorization = headers['Authorization'] 37 | encoded_token = authorization.split(" ")[1] 38 | 39 | if ((len(encoded_token) > 0) and (encoded_token.count('.') == 3)): 40 | try: 41 | payload = jwt.decode(encoded_token, cls.secret, algorithms=["HS256"]) 42 | roles = list(payload['roles']) 43 | 44 | if 'Administrator' in roles: 45 | return True 46 | return False 47 | except (jwt.ExpiredSignatureError, jwt.InvalidSignatureError): 48 | return False 49 | 50 | return False 51 | except Exception as ex: 52 | Logger.add_to_log("error", str(ex)) 53 | Logger.add_to_log("error", traceback.format_exc()) 54 | -------------------------------------------------------------------------------- /src/utils/log/app.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UskoKruM/flask-folders-structure/188e6bd66907e8879b9d1220a93e8046b21846be/src/utils/log/app.log --------------------------------------------------------------------------------