Skip to content

Commit 40bbefc

Browse files
authored
Merge pull request #115 from tecladocode/develop
2 parents 5d38a64 + 29e52cd commit 40bbefc

File tree

156 files changed

+4677
-129
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

156 files changed

+4677
-129
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ __pycache__/
77
venv/
88
.venv/
99
docs/docs/.nota/config.ini
10+
section-start-code.zip
11+
section-end-code.zip
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.venv
2+
*.pyc
3+
__pycache__
4+
data.db
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FLASK_APP=app
2+
FLASK_DEBUG=True
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM python:3.10
2+
EXPOSE 5000
3+
WORKDIR /app
4+
COPY ./requirements.txt requirements.txt
5+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
6+
COPY . .
7+
CMD ["flask", "run", "--host", "0.0.0.0"]
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from flask import Flask, jsonify
2+
from flask_smorest import Api
3+
from flask_jwt_extended import JWTManager
4+
5+
from db import db
6+
from blocklist import BLOCKLIST
7+
8+
from resources.user import blp as UserBlueprint
9+
from resources.item import blp as ItemBlueprint
10+
from resources.store import blp as StoreBlueprint
11+
from resources.tag import blp as TagBlueprint
12+
13+
14+
def create_app(db_url=None):
15+
app = Flask(__name__)
16+
app.config["API_TITLE"] = "Stores REST API"
17+
app.config["API_VERSION"] = "v1"
18+
app.config["OPENAPI_VERSION"] = "3.0.3"
19+
app.config["OPENAPI_URL_PREFIX"] = "/"
20+
app.config["OPENAPI_SWAGGER_UI_PATH"] = "/swagger-ui"
21+
app.config[
22+
"OPENAPI_SWAGGER_UI_URL"
23+
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist/"
24+
app.config["SQLALCHEMY_DATABASE_URI"] = db_url or "sqlite:///data.db"
25+
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
26+
app.config["PROPAGATE_EXCEPTIONS"] = True
27+
db.init_app(app)
28+
api = Api(app)
29+
30+
app.config["JWT_SECRET_KEY"] = "jose"
31+
jwt = JWTManager(app)
32+
33+
# @jwt.additional_claims_loader
34+
# def add_claims_to_jwt(identity):
35+
# # TODO: Read from a config file instead of hard-coding
36+
# if identity == 1:
37+
# return {"is_admin": True}
38+
# return {"is_admin": False}
39+
40+
@jwt.token_in_blocklist_loader
41+
def check_if_token_in_blocklist(jwt_header, jwt_payload):
42+
return jwt_payload["jti"] in BLOCKLIST
43+
44+
@jwt.expired_token_loader
45+
def expired_token_callback(jwt_header, jwt_payload):
46+
return (
47+
jsonify({"message": "The token has expired.", "error": "token_expired"}),
48+
401,
49+
)
50+
51+
@jwt.invalid_token_loader
52+
def invalid_token_callback(error):
53+
return (
54+
jsonify(
55+
{"message": "Signature verification failed.", "error": "invalid_token"}
56+
),
57+
401,
58+
)
59+
60+
@jwt.unauthorized_loader
61+
def missing_token_callback(error):
62+
return (
63+
jsonify(
64+
{
65+
"description": "Request does not contain an access token.",
66+
"error": "authorization_required",
67+
}
68+
),
69+
401,
70+
)
71+
72+
@jwt.needs_fresh_token_loader
73+
def token_not_fresh_callback(jwt_header, jwt_payload):
74+
return (
75+
jsonify(
76+
{
77+
"description": "The token is not fresh.",
78+
"error": "fresh_token_required",
79+
}
80+
),
81+
401,
82+
)
83+
84+
@jwt.revoked_token_loader
85+
def revoked_token_callback(jwt_header, jwt_payload):
86+
return (
87+
jsonify(
88+
{"description": "The token has been revoked.", "error": "token_revoked"}
89+
),
90+
401,
91+
)
92+
93+
# JWT configuration ends
94+
95+
with app.app_context():
96+
import models # noqa: F401
97+
98+
db.create_all()
99+
100+
api.register_blueprint(UserBlueprint)
101+
api.register_blueprint(ItemBlueprint)
102+
api.register_blueprint(StoreBlueprint)
103+
api.register_blueprint(TagBlueprint)
104+
105+
return app
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""
2+
blocklist.py
3+
4+
This file just contains the blocklist of the JWT tokens. It will be imported by
5+
app and the logout resource so that tokens can be added to the blocklist when the
6+
user logs out.
7+
"""
8+
9+
BLOCKLIST = set()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from flask_sqlalchemy import SQLAlchemy
2+
3+
db = SQLAlchemy()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from models.user import UserModel
2+
from models.item import ItemModel
3+
from models.tag import TagModel
4+
from models.store import StoreModel
5+
from models.item_tags import ItemsTags
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from db import db
2+
3+
4+
class ItemModel(db.Model):
5+
__tablename__ = "items"
6+
7+
id = db.Column(db.Integer, primary_key=True)
8+
name = db.Column(db.String(80), unique=False, nullable=False)
9+
price = db.Column(db.Float(precision=2), unique=False, nullable=False)
10+
11+
store_id = db.Column(
12+
db.Integer, db.ForeignKey("stores.id"), unique=False, nullable=False
13+
)
14+
store = db.relationship("StoreModel", back_populates="items")
15+
16+
tags = db.relationship("TagModel", back_populates="items", secondary="items_tags")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from db import db
2+
3+
4+
class ItemsTags(db.Model):
5+
__tablename__ = "items_tags"
6+
7+
id = db.Column(db.Integer, primary_key=True)
8+
item_id = db.Column(db.Integer, db.ForeignKey("items.id"))
9+
tag_id = db.Column(db.Integer, db.ForeignKey("tags.id"))

0 commit comments

Comments
 (0)