Skip to content

Commit 40bbefc

Browse files
authored
Merge pull request tecladocode#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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy