|
1 | | -import os |
2 | | -from datetime import timedelta |
| 1 | +from flask import Flask |
3 | 2 |
|
4 | | -from flask import Flask, jsonify |
5 | | -from flask_jwt_extended import JWTManager |
6 | | -from flask_migrate import Migrate |
7 | | -from flask_sqlalchemy import SQLAlchemy |
8 | | -from dotenv import load_dotenv |
9 | | -from sqlalchemy import MetaData |
10 | | -from flask_smorest import Api |
| 3 | +from app.extensions import api, db, jwt, migrate |
| 4 | +from config import DevelopmentConfig |
11 | 5 |
|
12 | 6 |
|
13 | | -def register_blueprints(): |
| 7 | +def create_app(config_class=DevelopmentConfig): |
| 8 | + app = Flask(__name__) |
| 9 | + app.config.from_object(config_class) |
| 10 | + |
| 11 | + # initialize extensions |
| 12 | + db.init_app(app) |
| 13 | + migrate.init_app(app, db) |
| 14 | + jwt.init_app(app) |
| 15 | + api.init_app(app) |
| 16 | + |
| 17 | + # register blueprints |
| 18 | + from app.routes.auth import bp as auth_bp |
14 | 19 | from app.routes.category import bp as category_bp |
15 | | - from app.routes.subcategory import bp as subcategory_bp |
16 | 20 | from app.routes.product import bp as product_bp |
17 | | - from app.routes.auth import bp as auth_bp |
| 21 | + from app.routes.subcategory import bp as subcategory_bp |
18 | 22 |
|
19 | 23 | api.register_blueprint(category_bp, url_prefix="/categories") |
20 | 24 | api.register_blueprint(subcategory_bp, url_prefix="/subcategories") |
21 | 25 | api.register_blueprint(product_bp, url_prefix="/products") |
22 | 26 | api.register_blueprint(auth_bp, url_prefix="/auth") |
23 | 27 |
|
24 | | - |
25 | | -app = Flask(__name__) |
26 | | - |
27 | | -load_dotenv() |
28 | | - |
29 | | -# sqlalchemy |
30 | | -app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv("SQLALCHEMY_DATABASE_URI") |
31 | | -app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
32 | | - |
33 | | -# jwt |
34 | | -app.config["JWT_SECRET_KEY"] = os.getenv("JWT_SECRET_KEY") |
35 | | -app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=3) |
36 | | -app.config["JWT_REFRESH_TOKEN_EXPIRES"] = timedelta(days=3) |
37 | | - |
38 | | -# flask-smorest |
39 | | -app.config["API_TITLE"] = "Ecommerce REST API" |
40 | | -app.config["API_VERSION"] = "v1" |
41 | | -app.config["OPENAPI_VERSION"] = "3.0.2" |
42 | | - |
43 | | -# flask-smorest openapi swagger |
44 | | -app.config["OPENAPI_URL_PREFIX"] = "/" |
45 | | -app.config["OPENAPI_SWAGGER_UI_PATH"] = "/" |
46 | | -app.config["OPENAPI_SWAGGER_UI_URL"] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist/" |
47 | | - |
48 | | -# flask-smorest Swagger UI top level authorize dialog box |
49 | | -app.config["API_SPEC_OPTIONS"] = { |
50 | | - "components": { |
51 | | - "securitySchemes": { |
52 | | - "access_token": { |
53 | | - "type": "http", |
54 | | - "scheme": "bearer", |
55 | | - "bearerFormat": "JWT", |
56 | | - "description": "Enter your JWT access token", |
57 | | - }, |
58 | | - "refresh_token": { |
59 | | - "type": "http", |
60 | | - "scheme": "bearer", |
61 | | - "bearerFormat": "JWT", |
62 | | - "description": "Enter your JWT refresh token", |
63 | | - }, |
64 | | - } |
65 | | - } |
66 | | -} |
67 | | - |
68 | | -# PostgreSQL-compatible naming convention (to follow the naming convention already used in the DB) |
69 | | -# https://stackoverflow.com/questions/4107915/postgresql-default-constraint-names |
70 | | -naming_convention = { |
71 | | - "ix": "%(table_name)s_%(column_0_name)s_idx", # Indexes |
72 | | - "uq": "%(table_name)s_%(column_0_name)s_key", # Unique constraints |
73 | | - "ck": "%(table_name)s_%(constraint_name)s_check", # Check constraints |
74 | | - "fk": "%(table_name)s_%(column_0_name)s_fkey", # Foreign keys |
75 | | - "pk": "%(table_name)s_pkey" # Primary keys |
76 | | -} |
77 | | -metadata = MetaData(naming_convention=naming_convention) |
78 | | -db = SQLAlchemy(app, metadata=metadata) |
79 | | -migrate = Migrate(app, db) |
80 | | -jwt = JWTManager(app) |
81 | | -api = Api(app) |
82 | | - |
83 | | -register_blueprints() |
84 | | - |
85 | | - |
86 | | -@jwt.expired_token_loader |
87 | | -def expired_token_callback(jwt_header, jwt_payload): |
88 | | - err = "Access token expired. Use your refresh token to get a new one." |
89 | | - if jwt_payload['type'] == 'refresh': |
90 | | - err = "Refresh token expired. Please login again." |
91 | | - return jsonify(code="token_expired", error=err), 401 |
92 | | - |
93 | | -@jwt.invalid_token_loader |
94 | | -def invalid_token_callback(error): |
95 | | - return jsonify(code="invalid_token", error="Invalid token provided."), 401 |
96 | | - |
97 | | -@jwt.unauthorized_loader |
98 | | -def missing_token_callback(error): |
99 | | - return jsonify(code="authorization_required", error="JWT needed for this operation. Login, if needed."), 401 |
| 28 | + return app |
0 commit comments