diff --git a/.env b/.env new file mode 100644 index 0000000..d147fc6 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +TEST_DATABASE_URL=postgresql://dev_user:motdepassedev@51.255.51.83:5433/dev_db +FLASK_ENV="development" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 15201ac..39c5882 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +#.env +migrations/ + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -128,7 +131,7 @@ celerybeat.pid *.sage.py # Environments -.env +#.env .venv env/ venv/ diff --git a/Dockerfile b/Dockerfile index a38b6e1..e83726a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,9 +2,13 @@ FROM python:3.11-slim COPY requirements.txt . +RUN apt update && apt install -y git && rm -rf /var/lib/apt/lists/* +RUN pip install --upgrade pip RUN pip install -r requirements.txt -COPY . . +COPY . . -ENTRYPOINT ["flask"] -CMD ["run"] -EXPOSE 5000 \ No newline at end of file +CMD ["python","app.py"] + +#ENTRYPOINT ["flask"] +#CMD ["run"] +#EXPOSE 5000 \ No newline at end of file diff --git a/app.py b/app.py index 6a21f8f..8247e71 100644 --- a/app.py +++ b/app.py @@ -3,4 +3,5 @@ app = create_app() if __name__ == "__main__": #lancement de l'app - app.run(debug=app.config.get("DEBUG")) + app.run(host="0.0.0.0", port=5000, debug=True) + # app.run(debug=app.config.get("DEBUG")) diff --git a/app/__init__.py b/app/__init__.py index e0ec4f5..3b472ee 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,26 +1,32 @@ -from flask import Flask,jsonify +from flask import Flask, jsonify from app.config import * -from app.extensions import jwt -import os +from app.extensions import jwt, db +import os from dotenv import load_dotenv __version__ = "1.0.1" # géré automatiquement par la CI + load_dotenv(".env") def create_app(): - app = Flask(__name__) + app = Flask(__name__) + + + app.config.from_object(config[os.getenv("FLASK_ENV") or "development"])#en mode dev par défaut si rien de spécifié + + + db.init_app(app) + jwt.init_app(app) + + @jwt.unauthorized_loader # gérer le cas ou le client n'est pas authentifié + def unauthorized_callback(callback): + return jsonify({"msg": "Token invalide ou manquant. veuillez vous authentifier."}), 401 - app.config.from_object(config[os.getenv("FLASK_ENV") or "development"])#en mode dev par défaut si rien de spécifié - #db.init_app(app) - jwt.init_app(app) + from app.routes.routes1 import projets_bp - @jwt.unauthorized_loader # gérer le cas ou le client n'est pas authentifié - def unauthorized_callback(callback): - return jsonify({"msg": "Token invalide ou manquant. veuillez vous authentifier."}), 401 - from app.routes.routes1 import test_bp + app.register_blueprint(projets_bp, url_prefix='/projets') - app.register_blueprint(test_bp, url_prefix='/test') - return app + return app \ No newline at end of file diff --git a/app/config.py b/app/config.py index 8bd9e0b..a5cf5fe 100644 --- a/app/config.py +++ b/app/config.py @@ -9,7 +9,7 @@ class Config: # config par défaut JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY', 'enormemotdepasse') PORT=os.getenv("FLASK_PORT",5000) -class DevelopmentConfig(Config): +class DevelopmentConfig(Config): FLASK_ENV = 'development' DEBUG = True SQLALCHEMY_DATABASE_URI = os.getenv('DEV_DATABASE_URL', 'postgresql://user:password@db:5432/basededev') diff --git a/app/extensions.py b/app/extensions.py index 1b0b96c..d68a2e7 100644 --- a/app/extensions.py +++ b/app/extensions.py @@ -1,7 +1,9 @@ from flask_sqlalchemy import SQLAlchemy from flask_jwt_extended import JWTManager +from depsec_db.extensions import db + +db = db #from depsec_models.database import db -#db= depsec_models.database.db -jwt = JWTManager() +jwt = JWTManager() \ No newline at end of file diff --git a/app/routes/routes1.py b/app/routes/routes1.py index 2b8f78b..1a1aa10 100644 --- a/app/routes/routes1.py +++ b/app/routes/routes1.py @@ -1,34 +1,132 @@ -from flask import Blueprint, request, jsonify +from flask import Blueprint, current_app, json, request, jsonify from flask_jwt_extended import create_access_token -#from app.extensions import db +from app.extensions import db from flask_limiter import Limiter from flask_limiter.util import get_remote_address import re from app.services.auth import verify_token -from flask import current_app +from app.extensions import db +from depsec_db import models #from depsec_models.models import * #import des modèles depuis le package -test_bp = Blueprint("test", __name__) + +projets_bp = Blueprint("projets", __name__) limiter = Limiter(get_remote_address, default_limits=["5 per minute"]) -@test_bp.route('/toto', methods=['GET']) -def toto(): + +# ---------- Phase de test avant la BDD (comme si test.json était ce qu'on récupérait de la BDD) ------------- # + + +projects = [ + { + "id":1, + "titre":"Gestion des projets", + "auteur":"Solayman", + "status":"Accept", + "path":"/var/sui" + }, + { + "id":2, + "titre":"Gestion de BDD", + "auteur":"Pierrot la pinto de la mañana", + "status":"Refuse", + "path":"/var/bang" + } +] + + +def return_all_proj(): + return projects + + +def return_project(proj): + for p in projects: + if proj in p.values(): + return p + + +def add_dico(dico): + + for d in projects: + if d["titre"] == dico["titre"]: + return jsonify({"error": f"Le nom de projet {d['titre']} existe deja !"}), 400 + + # trouve le + grand id + max_id = max([elem['id'] for elem in projects]) if projects else 0 + + dico['id'] = max_id + 1 + projects.append(dico) + + return return_all_proj() + #save_json(file_path, data) + #return jsonify(load_json(file_path)), 200 + +def del_dico(id): + global projects + + try: + new_data = [item for item in projects if int(item.get("id")) != int(id)] + except : + return jsonify({"error": "Entrez un entier !"}), 404 + + if len(new_data) == len(projects): + return jsonify({"error": f"Le projet avec l'id '{id}' n'existe pas !"}), 404 + + projects = new_data + return return_all_proj() + #return jsonify(load_json(file_path)), 200 + +# ------------------------------------------------------------------------------------------------------------ # + + +@projets_bp.route('/', methods=['GET']) +def get_projects(): if verify_token() == False and current_app.config["FLASK_ENV"] !="development" : #verifier que le token est valide ( a mettre dans chaque route) et qu'on est pas en environnement de dev return jsonify({"msg": "Token invalide / Utilisateur non autorisé"}), 401 - data = request.json - return jsonify({"msg":"blabla cool"}), 200 -@test_bp.route('/tutu', methods=['POST']) -@limiter.limit("5 per minute") #exemple pouur limiter le nombre de requetes -def tutu(): + #data = request.get_json() + + + #return return_all_proj(), 200 + #return jsonify({"Projects":data.get('titre')}), 200 + + #projects = Project.query.all() + #return jsonify([user.to_dict() for user in users]) + + +@projets_bp.route('/', methods=['POST']) +def add_project(): if verify_token() == False and current_app.config["FLASK_ENV"] !="development" : #verifier que le token est valide ( a mettre dans chaque route) et qu'on est pas en environnement de dev return jsonify({"msg": "Token invalide / Utilisateur non autorisé"}), 401 - data = request.json - return jsonify({"msg": "blabla"}), 401 + data = request.get_json() + if not data : + return jsonify({"error": "Le fomat de vos donnees n'est pas bon !!"}), 400 + if data.get("titre") and data.get("auteur") and data.get("status") and data.get("path"): + titre = data.get("titre") + auteur = data.get("auteur") + status = data.get("status") + path = data.get("path") + if isinstance(auteur, str) and status in ["Accept","Refuse"]: + format = { + "id":0, + "titre":titre, + "auteur":auteur, + "status":status, + "path":path + } + return add_dico(format) + else : + return jsonify({'error': 'Parametres aux mauvais formats !'}), 400 + else : + return jsonify({'error': 'Parametres manquants'}), 400 + +@projets_bp.route("/", methods=["DELETE"]) +def del_project(id): + return del_dico(id) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 0d114c7..7739bdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] -name = "TemplateAPI" # achanger -description = "Template d'API pour le projet DEPSEC" # achanger +name = "API_Project_Management" # achanger +description = "API_Project_Management nous permet de gérer nos projets grr baw" # achanger [tool.semantic_release] version_variable = ["app/__init__.py:__version__"] @@ -17,4 +17,3 @@ tag_format = "v{version}" #tag git automatique pour semantic-release changelog_sections = ["Features", "Bug Fixes", "Documentation", "Tests","CI/CD"] upload_to_release = true # release auto sur github changelog_format = "- {message} ([{commit}](https://github.com/DEPSEC-Project/TemplateAPI/commit/{commit}))" - diff --git a/requirements.txt b/requirements.txt index 633fc5d..5ccf151 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +pip==20.3.4 flask flask-limiter Flask-SQLAlchemy @@ -5,4 +6,8 @@ Flask-JWT-Extended pytest dotenv requests -python-semantic-release \ No newline at end of file +python-semantic-release +setuptools +flask_migrate +psycopg2-binary +git+https://github.com/DEPSEC-Project/DB-Management.git \ No newline at end of file diff --git a/test/test_app.py b/test/test_app.py index af6e783..1f3ed70 100644 --- a/test/test_app.py +++ b/test/test_app.py @@ -3,5 +3,4 @@ def test_inutile(): """ A modifier si on décide de définir des tests unitaires """ - assert True - \ No newline at end of file + assert True \ No newline at end of file