From b9fc26348d2b905daa6e59fbab36584335ad8356 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Thu, 29 Jun 2023 23:22:46 +0200 Subject: [PATCH 01/10] snif --- src/blueprints/auth.py | 3 +-- src/blueprints/favoris.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/blueprints/auth.py b/src/blueprints/auth.py index 42210e4..2ae5c74 100644 --- a/src/blueprints/auth.py +++ b/src/blueprints/auth.py @@ -13,7 +13,6 @@ from src.constants.http_status_codes import ( HTTP_200_OK, HTTP_201_CREATED, - HTTP_204_NO_CONTENT, HTTP_400_BAD_REQUEST, HTTP_401_UNAUTHORIZED, HTTP_404_NOT_FOUND, @@ -251,4 +250,4 @@ def remove_user() -> Tuple[Response, int] | HTTPException: db.session.delete(user) db.session.commit() - return jsonify({}), HTTP_204_NO_CONTENT + return jsonify({}), HTTP_200_OK diff --git a/src/blueprints/favoris.py b/src/blueprints/favoris.py index cfc7b9b..33a340b 100644 --- a/src/blueprints/favoris.py +++ b/src/blueprints/favoris.py @@ -7,7 +7,6 @@ from src.constants.http_status_codes import ( HTTP_200_OK, HTTP_201_CREATED, - HTTP_204_NO_CONTENT, HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND, HTTP_409_CONFLICT, @@ -70,4 +69,4 @@ def remove_favori(id: int) -> Tuple[Response, int] | HTTPException: db.session.delete(favori) db.session.commit() - return jsonify({}), HTTP_204_NO_CONTENT + return jsonify({}), HTTP_200_OK From 10755aba734b28b2d579fc489000254dfbb183d4 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Fri, 30 Jun 2023 11:50:18 +0200 Subject: [PATCH 02/10] remove name update schema --- config.py | 2 +- src/blueprints/auth.py | 12 +----------- src/docs/auth/login/register.yaml | 4 ---- src/models/user.py | 6 ++---- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/config.py b/config.py index 7b2a509..0995f40 100644 --- a/config.py +++ b/config.py @@ -29,7 +29,7 @@ class Config(object): class DevelopmentConfig(Config): DEBUG = True - SQLALCHEMY_DATABASE_URI = get_dev_db_uri() + SQLALCHEMY_DATABASE_URI = get_prod_db_uri() class ProductionConfig(Config): diff --git a/src/blueprints/auth.py b/src/blueprints/auth.py index 2ae5c74..13d4417 100644 --- a/src/blueprints/auth.py +++ b/src/blueprints/auth.py @@ -36,7 +36,6 @@ def register() -> Tuple[Response, int] | HTTPException: data = request.json if data is not None: username = data.get("username") - name = data.get("name") email = data.get("email") password = data.get("password") @@ -51,9 +50,6 @@ def register() -> Tuple[Response, int] | HTTPException: abort( HTTP_400_BAD_REQUEST, "Username shloud be alphanumeric, also no spaces" ) - # Verify if name have alphanumeric characters or space - if not name.isalnum() or " " in name: - abort(HTTP_400_BAD_REQUEST, "Name shloud be alphanumeric, also no spaces") # Verify with "validators" if email is valid if not validators.email(email): abort(HTTP_409_CONFLICT, "Email is not valid") @@ -66,7 +62,7 @@ def register() -> Tuple[Response, int] | HTTPException: # Hash password pwd_hash = generate_password_hash(password) - user = User(username=username, password=pwd_hash, email=email, name=name) + user = User(username=username, password=pwd_hash, email=email) db.session.add(user) db.session.commit() @@ -166,7 +162,6 @@ def edit_user() -> Tuple[Response, int] | HTTPException: if data is not None: username = data.get("username", user.username) - name = data.get("name", user.name) pdp_url = data.get("pdp_url", user.pdp_url) email = data.get("email", user.email) password = data.get("password") @@ -184,11 +179,6 @@ def edit_user() -> Tuple[Response, int] | HTTPException: errors["username"] = "Username is taken" else: user.username = username - if name != user.name: - if not name.isalnum() or " " in name: - errors["name"] = "Name should be alphanumeric, also no spaces" - else: - user.name = name if pdp_url != user.pdp_url: user.pdp_url = pdp_url diff --git a/src/docs/auth/login/register.yaml b/src/docs/auth/login/register.yaml index b9ceda2..b40bd28 100644 --- a/src/docs/auth/login/register.yaml +++ b/src/docs/auth/login/register.yaml @@ -12,7 +12,6 @@ parameters: required: - "email" - "password" - - "name" - "usermame" properties: email: @@ -22,9 +21,6 @@ parameters: type: "string" format: password example: "********" - name: - type: "name" - example: "myname" username: type: "username" example: "Jojo" diff --git a/src/models/user.py b/src/models/user.py index bc79fdd..d6994b0 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -10,16 +10,14 @@ class User(db.Model): id: int username: str - name: str email: str - pdp_url: str + profile_pic_url: str id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) - name = db.Column(db.String(200), nullable=False) email = db.Column(db.String(200), unique=True, nullable=False) password = db.Column(db.Text(), nullable=False) - pdp_url = db.Column(db.Text) + profile_pic_url = db.Column(db.Text) favoris = db.relationship("Favori", backref="user") def __repr__(self) -> str: From feb560931f2258dbc71a7cde04a6d1c37b90c9b8 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Fri, 30 Jun 2023 11:51:35 +0200 Subject: [PATCH 03/10] add migration --- .gitignore | 2 - migrations/README | 1 + migrations/alembic.ini | 50 +++++++++++++++ migrations/env.py | 91 ++++++++++++++++++++++++++++ migrations/script.py.mako | 24 ++++++++ migrations/versions/47c4e50f11de_.py | 62 +++++++++++++++++++ migrations/versions/8ce7337ffbf4_.py | 45 ++++++++++++++ 7 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 migrations/README create mode 100644 migrations/alembic.ini create mode 100644 migrations/env.py create mode 100644 migrations/script.py.mako create mode 100644 migrations/versions/47c4e50f11de_.py create mode 100644 migrations/versions/8ce7337ffbf4_.py diff --git a/.gitignore b/.gitignore index 67640c9..8c033bd 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,6 @@ __pycache__/ *.Spy.class *.pyc -#migration ignore -migrations/* #Ignore variable env .flaskenv diff --git a/migrations/README b/migrations/README new file mode 100644 index 0000000..0e04844 --- /dev/null +++ b/migrations/README @@ -0,0 +1 @@ +Single-database configuration for Flask. diff --git a/migrations/alembic.ini b/migrations/alembic.ini new file mode 100644 index 0000000..ec9d45c --- /dev/null +++ b/migrations/alembic.ini @@ -0,0 +1,50 @@ +# A generic, single database configuration. + +[alembic] +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic,flask_migrate + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[logger_flask_migrate] +level = INFO +handlers = +qualname = flask_migrate + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/migrations/env.py b/migrations/env.py new file mode 100644 index 0000000..68feded --- /dev/null +++ b/migrations/env.py @@ -0,0 +1,91 @@ +from __future__ import with_statement + +import logging +from logging.config import fileConfig + +from flask import current_app + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) +logger = logging.getLogger('alembic.env') + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +config.set_main_option( + 'sqlalchemy.url', + str(current_app.extensions['migrate'].db.get_engine().url).replace( + '%', '%%')) +target_metadata = current_app.extensions['migrate'].db.metadata + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, 'autogenerate', False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info('No changes in schema detected.') + + connectable = current_app.extensions['migrate'].db.get_engine() + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions['migrate'].configure_args + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako new file mode 100644 index 0000000..2c01563 --- /dev/null +++ b/migrations/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/47c4e50f11de_.py b/migrations/versions/47c4e50f11de_.py new file mode 100644 index 0000000..b3ad164 --- /dev/null +++ b/migrations/versions/47c4e50f11de_.py @@ -0,0 +1,62 @@ +"""empty message + +Revision ID: 47c4e50f11de +Revises: +Create Date: 2023-04-30 19:49:07.901489 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "47c4e50f11de" +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "user", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("username", sa.String(length=80), nullable=False), + sa.Column("name", sa.String(length=200), nullable=False), + sa.Column("email", sa.String(length=200), nullable=False), + sa.Column("password", sa.Text(), nullable=False), + sa.Column("pdp_url", sa.Text(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("email"), + sa.UniqueConstraint("username"), + ) + op.create_table( + "favori", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("code_nsf", sa.Text(), nullable=True), + sa.Column("sigle_type_formation", sa.Text(), nullable=True), + sa.Column("libelle_type_formation", sa.Text(), nullable=True), + sa.Column("libelle_formation_principal", sa.Text(), nullable=True), + sa.Column("sigle_formation", sa.Text(), nullable=True), + sa.Column("duree", sa.Text(), nullable=True), + sa.Column("niveau_de_sortie_indicatif", sa.Text(), nullable=True), + sa.Column("code_rncp", sa.Text(), nullable=True), + sa.Column("niveau_de_certification", sa.Text(), nullable=True), + sa.Column("libelle_niveau_de_certification", sa.Text(), nullable=True), + sa.Column("tutelle", sa.Text(), nullable=True), + sa.Column("url_et_id_onisep", sa.Text(), nullable=False), + sa.Column("request_user_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["request_user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table("favori") + op.drop_table("user") + # ### end Alembic commands ### diff --git a/migrations/versions/8ce7337ffbf4_.py b/migrations/versions/8ce7337ffbf4_.py new file mode 100644 index 0000000..d602ed5 --- /dev/null +++ b/migrations/versions/8ce7337ffbf4_.py @@ -0,0 +1,45 @@ +"""empty message + +Revision ID: 8ce7337ffbf4 +Revises: 47c4e50f11de +Create Date: 2023-06-30 11:47:16.940598 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision = "8ce7337ffbf4" +down_revision = "47c4e50f11de" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("user", sa.Column("profile_pic_url", sa.Text(), nullable=True)) + op.drop_column("user", "pdp_url") + op.drop_column("user", "name") + op.add_column("user", sa.Column("created_at", sa.DateTime(), nullable=True)) + op.add_column("user", sa.Column("updated_at", sa.DateTime(), nullable=True)) + op.execute("UPDATE user SET created_at = now()") + op.execute("UPDATE user SET updated_at = now()") + op.alter_column("user", "created_at", existing_type=sa.DateTime(), nullable=False) + op.alter_column("user", "updated_at", existing_type=sa.DateTime(), nullable=False) + + op.add_column("favori", sa.Column("created_at", sa.DateTime(), nullable=True)) + op.add_column("favori", sa.Column("updated_at", sa.DateTime(), nullable=True)) + op.execute("UPDATE favori SET created_at = now()") + op.execute("UPDATE favori SET updated_at = now()") + op.alter_column("favori", "created_at", existing_type=sa.DateTime(), nullable=False) + op.alter_column("favori", "updated_at", existing_type=sa.DateTime(), nullable=False) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("user", sa.Column("name", mysql.VARCHAR(length=200), nullable=False)) + op.add_column("user", sa.Column("pdp_url", mysql.TEXT(), nullable=True)) + op.drop_column("user", "profile_pic_url") + # ### end Alembic commands ### From 4212218c19f842650d58ad59a232ac2216afa197 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Fri, 30 Jun 2023 11:52:09 +0200 Subject: [PATCH 04/10] Drop files from .gitignore --- .env | 4 ---- Dockerfile | 23 ----------------------- 2 files changed, 27 deletions(-) delete mode 100644 .env delete mode 100644 Dockerfile diff --git a/.env b/.env deleted file mode 100644 index fb61b68..0000000 --- a/.env +++ /dev/null @@ -1,4 +0,0 @@ -ENV=dev -FLASK_APP=src -JWT_SECRET_KEY='JWT_SECRET_KEY' -SECRET_KEY=devs diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4f1e5ff..0000000 --- a/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM python:slim-buster AS build -ENV PYTHONUNBUFFERED 1 - -LABEL authors="Angel-Dijoux" - -WORKDIR /app - -ENV ENV=production -ENV FLASK_APP=src - - -COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt - -COPY . . - -COPY entrypoint.sh / -RUN chmod +x /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 5005 - -CMD ["gunicorn", "run:app" ,"-c" ,"gunicorn.conf.py" ] \ No newline at end of file From 424b92cc69a6095e377779c938292d4d3a8b8ed2 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Fri, 30 Jun 2023 11:59:48 +0200 Subject: [PATCH 05/10] update model --- src/models/base_model.py | 13 +++++++++++++ src/models/favori.py | 6 ++---- src/models/user.py | 7 +++---- 3 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 src/models/base_model.py diff --git a/src/models/base_model.py b/src/models/base_model.py new file mode 100644 index 0000000..0c7d46e --- /dev/null +++ b/src/models/base_model.py @@ -0,0 +1,13 @@ +from src import db +from sqlalchemy import func + + +class BaseModel(db.Model): + __abstract__: bool = True + created_at = db.Column(db.DateTime, nullable=False, default=func.now()) + updated_at = db.Column( + db.DateTime, nullable=False, default=func.now(), onupdate=func.now() + ) + + def to_dict(self): + return {field.name: getattr(self, field.name) for field in self.__table__.c} diff --git a/src/models/favori.py b/src/models/favori.py index 4be7a52..e42b564 100644 --- a/src/models/favori.py +++ b/src/models/favori.py @@ -1,9 +1,10 @@ from dataclasses import dataclass from src import db +from src.models.base_model import BaseModel @dataclass -class Favori(db.Model): +class Favori(BaseModel): __tablename__ = "favori" id: int @@ -35,6 +36,3 @@ class Favori(db.Model): tutelle = db.Column(db.Text) url_et_id_onisep = db.Column(db.Text, nullable=False) request_user_id = db.Column(db.Integer, db.ForeignKey("user.id")) - - def __repr__(self) -> str: - return "Favori>>> {self.onisep_url}" diff --git a/src/models/user.py b/src/models/user.py index d6994b0..80428b3 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -1,11 +1,13 @@ from dataclasses import dataclass from src import db +from src.models.base_model import BaseModel + # Create User row @dataclass -class User(db.Model): +class User(BaseModel): __tablename__ = "user" id: int @@ -19,6 +21,3 @@ class User(db.Model): password = db.Column(db.Text(), nullable=False) profile_pic_url = db.Column(db.Text) favoris = db.relationship("Favori", backref="user") - - def __repr__(self) -> str: - return "User>>> {self.username}" From ba3da0fbb550f22c76a724e5e59e600352befeb7 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Fri, 30 Jun 2023 12:09:16 +0200 Subject: [PATCH 06/10] little opti --- src/blueprints/auth.py | 14 +++----------- src/blueprints/favoris.py | 6 +++++- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/blueprints/auth.py b/src/blueprints/auth.py index 13d4417..ede2314 100644 --- a/src/blueprints/auth.py +++ b/src/blueprints/auth.py @@ -21,6 +21,7 @@ from src import db from src.models import User, Favori +import re from typing import Tuple @@ -39,17 +40,8 @@ def register() -> Tuple[Response, int] | HTTPException: email = data.get("email") password = data.get("password") - # Verify if password is large enought - if len(password) < 6: - abort(HTTP_400_BAD_REQUEST, "Password is too short") - # Verify if username is large enought - if len(username) < 3: - abort(HTTP_400_BAD_REQUEST, "Username is too short") - # Verify if username have alphanumeric characters or space - if not username.isalnum() or " " in username: - abort( - HTTP_400_BAD_REQUEST, "Username shloud be alphanumeric, also no spaces" - ) + if len(password) < 6 or not re.match(r"^[a-zA-Z0-9]{3,20}$", username): + abort(HTTP_400_BAD_REQUEST, "Invalid password or username") # Verify with "validators" if email is valid if not validators.email(email): abort(HTTP_409_CONFLICT, "Email is not valid") diff --git a/src/blueprints/favoris.py b/src/blueprints/favoris.py index 33a340b..7d54ce7 100644 --- a/src/blueprints/favoris.py +++ b/src/blueprints/favoris.py @@ -48,7 +48,11 @@ def post_favori_by_user_id() -> Tuple[Response, int] | HTTPException: @swag_from("../docs/favoris/getFavoris.yaml") def get_favoris_by_user_id() -> Tuple[Response, int]: current_user = get_jwt_identity() - favoris = Favori.query.filter_by(request_user_id=current_user).all() + favoris = ( + Favori.query.filter(Favori.request_user_id == current_user) + .order_by(Favori.created_at.asc()) + .all() + ) return jsonify({"size": len(favoris), "results": favoris}), HTTP_200_OK From ae9d72ac91e3a01be3e465f26f505ae32fa67888 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Fri, 30 Jun 2023 16:59:27 +0200 Subject: [PATCH 07/10] disable --- .github/workflows/deployment.yml | 12 ++++++------ src/blueprints/formations.py | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 828bf95..26aaa53 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -15,11 +15,11 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 - - name: Stop running Docker container - run: docker stop api - - name: remove container - run: docker rm api - - name: Remove previous Docker image - run: docker rmi onisep_api-api:latest + # - name: Stop running Docker container + # run: docker stop api + # - name: remove container + # run: docker rm api + # - name: Remove previous Docker image + # run: docker rmi onisep_api-api:latest - name: Build and Run Docker container run: docker-compose up -d diff --git a/src/blueprints/formations.py b/src/blueprints/formations.py index 7f0e27d..937bc20 100644 --- a/src/blueprints/formations.py +++ b/src/blueprints/formations.py @@ -7,7 +7,6 @@ from src.constants.http_status_codes import ( HTTP_200_OK, - HTTP_404_NOT_FOUND, HTTP_500_INTERNAL_SERVER_ERROR, ) @@ -25,7 +24,7 @@ def get_formation_by_id(id: str) -> Tuple[Response, int] | HTTPException: try: with open("assets/formation/data.json", "r") as json_file: result = filter_by_link(json.load(json_file)["formations"]["formation"], id) - return jsonify(result), HTTP_200_OK if len(result) > 0 else HTTP_404_NOT_FOUND + return jsonify(result), HTTP_200_OK if len(result) > 0 else HTTP_200_OK except Exception: print("Error in get_formation_by_id : ", Exception) abort(HTTP_500_INTERNAL_SERVER_ERROR) From fa0048536f55da188dc28983992c5f9af55cdd04 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Mon, 3 Jul 2023 00:16:10 +0200 Subject: [PATCH 08/10] add new route --- src/blueprints/favoris.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/blueprints/favoris.py b/src/blueprints/favoris.py index 7d54ce7..2aed400 100644 --- a/src/blueprints/favoris.py +++ b/src/blueprints/favoris.py @@ -13,6 +13,7 @@ ) from src import db from src.models import Favori +import base64 from typing import Tuple @@ -26,6 +27,7 @@ def post_favori_by_user_id() -> Tuple[Response, int] | HTTPException: current_user = get_jwt_identity() # Collect informations favori_data = request.get_json() + favori_data.pop("domainesous-domaine", None) if not validators.url(favori_data.get("url_et_id_onisep", "")): abort(HTTP_400_BAD_REQUEST, "Enter valid url") @@ -59,6 +61,19 @@ def get_favoris_by_user_id() -> Tuple[Response, int]: # Remove_favoris function need JWT token and delete favoris for this user +@favoris.route("/favori_ids") +@jwt_required() +def get_favoris_ids() -> Tuple[Response, int]: + current_user = get_jwt_identity() + result = ( + Favori.query.with_entities(Favori.url_et_id_onisep, Favori.id) + .filter(Favori.request_user_id == current_user) + .all() + ) + favori_data = [{"id": row.id, "url": row.url_et_id_onisep} for row in result] + return jsonify({"favori_ids": favori_data}), HTTP_200_OK + + @favoris.delete("/") @jwt_required() @swag_from("../docs/favoris/remove.yaml") From 4b894b48daf84feb69e7117c0ab329c113e96fce Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Mon, 3 Jul 2023 00:18:31 +0200 Subject: [PATCH 09/10] modified: src/blueprints/favoris.py --- src/blueprints/favoris.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/blueprints/favoris.py b/src/blueprints/favoris.py index 2aed400..2e4cfe3 100644 --- a/src/blueprints/favoris.py +++ b/src/blueprints/favoris.py @@ -13,7 +13,6 @@ ) from src import db from src.models import Favori -import base64 from typing import Tuple From bbdb8b75660e4471446d07eab403f0f23c63f4f0 Mon Sep 17 00:00:00 2001 From: Angel Dijoux Date: Mon, 3 Jul 2023 00:20:24 +0200 Subject: [PATCH 10/10] modified: migrations/versions/47c4e50f11de_.py --- migrations/versions/47c4e50f11de_.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/versions/47c4e50f11de_.py b/migrations/versions/47c4e50f11de_.py index b3ad164..4ce8f2d 100644 --- a/migrations/versions/47c4e50f11de_.py +++ b/migrations/versions/47c4e50f11de_.py @@ -1,7 +1,7 @@ """empty message Revision ID: 47c4e50f11de -Revises: +Revises: Create Date: 2023-04-30 19:49:07.901489 """