diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 66e404c..58a0997 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,31 +1,32 @@ name: Continuos Delivery - CD on: - workflow_run: - workflows: ["Continuos Integration - CI"] - types: - - completed + # workflow_run: + # workflows: ["Continuos Integration - CI"] + # types: + # - requested + workflow_dispatch: jobs: aws: runs-on: self-hosted - steps: - # Running API Container - - name: Pull Docker Image (API) - run: | - sudo docker image rm -f davilucciola/knockbank-api - sudo docker pull davilucciola/knockbank-api:latest +# steps: +# # Running API Container +# - name: Pull Docker Image (API) +# run: | +# sudo docker image rm -f davilucciola/knockbank-api +# sudo docker pull davilucciola/knockbank-api:latest - - name: Delete Old Container (API) - run: sudo docker rm -f knockbank-api || true +# - name: Delete Old Container (API) +# run: sudo docker rm -f knockbank-api || true - - name: Run Docker Container (API) - env: - TOKEN_SECRET: ${{ secrets.TOKEN_SECRET }} - SQLALCHEMY_DATABASE_URI: ${{ secrets.SQLALCHEMY_DATABASE_URI }} - run: | - sudo docker run --name knockbank-api -p 5000:5000 --restart=always \ - -e TOKEN_SECRET=$TOKEN_SECRET \ - -e SQLALCHEMY_DATABASE_URI=$SQLALCHEMY_DATABASE_URI \ - -d davilucciola/knockbank-api \ No newline at end of file +# - name: Run Docker Container (API) +# env: +# TOKEN_SECRET: ${{ secrets.TOKEN_SECRET }} +# SQLALCHEMY_DATABASE_URI: ${{ secrets.SQLALCHEMY_DATABASE_URI }} +# run: | +# sudo docker run --name knockbank-api -p 5000:5000 --restart=always \ +# -e TOKEN_SECRET=$TOKEN_SECRET \ +# -e SQLALCHEMY_DATABASE_URI=$SQLALCHEMY_DATABASE_URI \ +# -d davilucciola/knockbank-api \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96cc3ce..92a4490 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,21 +11,57 @@ jobs: steps: - uses: actions/checkout@v3 - # Login Dockerhub - - name: Login Dockerhub - env: - DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} - run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD + # API - Build + - name: Using Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + - name: Install Dependencies + run: | + cd server + pip install --upgrade pip + pip install --no-cache-dir poetry + poetry config virtualenvs.create false + poetry install - # API - Docker Image - - name: Build Docker Image (API) + # API - Tests + - name: Running Tests run: | cd server - docker build -t davilucciola/knockbank-api . + poetry run pytest + env: + TOKEN_SECRET: testkey + + # Web - Build + - name: Using NodeJS + uses: actions/setup-node@v4 + with: + node-version: "20.8.0" + - name: Building NextJS + run: | + cd client + npm install + npm run build + + # Web - Tests + # Work In Progress + + + # Login Dockerhub + # - name: Login Dockerhub + # env: + # DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + # DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + # run: docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD + + # # API - Docker Image + # - name: Build Docker Image (API) + # run: | + # cd server + # docker build -t davilucciola/knockbank-api . - - name: Push Docker Image (API) - run: docker push davilucciola/knockbank-api:latest + # - name: Push Docker Image (API) + # run: docker push davilucciola/knockbank-api:latest # Web - Docker Image # - name: Build Web Image diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 2c0519a..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Tests - -on: - push: - branches: [dev] - -jobs: - tests: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - # API - Build - - name: Using Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - name: Install Dependencies - run: | - cd server - pip install --upgrade pip - pip install --no-cache-dir poetry - poetry config virtualenvs.create false - poetry install - - # API - Tests - - name: Running Tests - run: | - cd server - poetry run pytest - env: - TOKEN_SECRET: testkey - - # Web - Build - - name: Using NodeJS - uses: actions/setup-node@v4 - with: - node-version: "20.8.0" - - name: Building NextJS - run: | - cd client - npm install - npm run build - - # Web - Tests - # Work In Progress \ No newline at end of file diff --git a/client/src/modules/account/components/my-account.tsx b/client/src/modules/account/components/my-account.tsx index 718cc51..74c9a7b 100644 --- a/client/src/modules/account/components/my-account.tsx +++ b/client/src/modules/account/components/my-account.tsx @@ -42,12 +42,12 @@ import { ArrowLeft, Lock, Pencil, User } from "@phosphor-icons/react/dist/ssr"; import { AccountContext } from "@/modules/account/contexts/account-context"; import { useToast } from "@/components/ui/use-toast"; import { AuthContext } from "@/modules/auth/contexts/auth-context"; -import { useUnauthorizedHandler } from "@/modules/auth/hooks/use-unauthorized-handler"; +import { useRouter } from "next/navigation"; export function MyAccount({ account }: { account: Account | null }) { + const router = useRouter(); const { toast } = useToast(); const { logout } = useContext(AuthContext); - const { verifyToken } = useUnauthorizedHandler(); const { fetchAccount, updateAccount, blockAccount } = useContext(AccountContext); const [open, setOpen] = useState(false); @@ -104,7 +104,7 @@ export function MyAccount({ account }: { account: Account | null }) { duration: toastDurationInMiliseconds, }); await logout(); - verifyToken(); + router.push("/"); } catch (error) { if (error instanceof Error) { toast({ diff --git a/deploy/Dockerfile b/deploy/Dockerfile new file mode 100644 index 0000000..67b3f0c --- /dev/null +++ b/deploy/Dockerfile @@ -0,0 +1,4 @@ +FROM nginx:alpine +RUN rm /etc/nginx/conf.d/default.conf +WORKDIR /etc/nginx/conf.d/ +COPY ./nginx.conf /etc/nginx/conf.d/ \ No newline at end of file diff --git a/deploy/nginx.conf b/deploy/nginx.conf new file mode 100644 index 0000000..8fe8d0e --- /dev/null +++ b/deploy/nginx.conf @@ -0,0 +1,29 @@ +upstream knockbank-api { + server api:5000; +} + +upstream knockbank-web { + server web:3000; +} + +server { + listen 80; + + location / { + proxy_pass http://knockbank-web; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'Upgrade'; + proxy_cache_bypass $http_upgrade; + } + + location /api { + proxy_pass http://knockbank-api; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'Upgrade'; + proxy_cache_bypass $http_upgrade; + } +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index be97fff..b82d265 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,20 +2,6 @@ version: '3.9' services: - web: - container_name: knockbank-web - build: - context: ./client - ports: - - "3000:3000" - - api: - container_name: knockbank-api - build: - context: ./server - ports: - - "5000:5000" - db: image: mysql:5.7 container_name: knockbank-db @@ -24,10 +10,32 @@ services: MYSQL_USER: 'admin' MYSQL_PASSWORD: 'admin' MYSQL_ROOT_PASSWORD: 'password' - ports: - - "3306:3306" volumes: - mysql-db:/var/lib/mysql + api: + container_name: knockbank-api + build: + context: ./server + depends_on: + - db + + web: + container_name: knockbank-web + build: + context: ./client + depends_on: + - api + + proxy: + container_name: nginx-proxy + restart: always + build: + context: ./deploy + depends_on: + - web + ports: + - "80:80" + volumes: mysql-db: \ No newline at end of file diff --git a/server/knockbankapi/__init__.py b/server/knockbankapi/__init__.py index 6e4de3c..89f7a07 100644 --- a/server/knockbankapi/__init__.py +++ b/server/knockbankapi/__init__.py @@ -1,4 +1,3 @@ -import tomllib from typing import Type from apiflask import APIFlask from flask_cors import CORS @@ -8,7 +7,13 @@ def create_app(config: Type[Config] = Config) -> APIFlask: # Flask APP - app = APIFlask(__name__, title=Config.API_TITLE) + app = APIFlask( + __name__, + title=Config.API_TITLE, + version=Config.API_VERSION, + docs_path="/api/docs", + spec_path="/api/openapi.json", + ) # Config CORS(app, origins=["*"]) @@ -17,15 +22,13 @@ def create_app(config: Type[Config] = Config) -> APIFlask: app.config.from_object(config) # Info - @app.get("/info") + @app.get(f"/api/info") def info(): - with open("./pyproject.toml", mode="rb") as pyproject: - version = tomllib.load(pyproject)["tool"]["poetry"]["version"] - return { - "title": Config.API_TITLE, - "description": Config.DESCRIPTION, - "version": version, - } + return { + "title": Config.API_TITLE, + "description": Config.DESCRIPTION, + "version": Config.API_VERSION, + } # Routers app.register_blueprint(auth_bp) diff --git a/server/knockbankapi/app/controllers/account_controller.py b/server/knockbankapi/app/controllers/account_controller.py index d703069..fff8a34 100644 --- a/server/knockbankapi/app/controllers/account_controller.py +++ b/server/knockbankapi/app/controllers/account_controller.py @@ -15,7 +15,7 @@ from knockbankapi.infra.repositories import TransactionRepository -account_bp = APIBlueprint("Account", __name__, url_prefix="/account") +account_bp = APIBlueprint("Account", __name__, url_prefix="/api/account") @account_bp.get("/me") diff --git a/server/knockbankapi/app/controllers/auth_controller.py b/server/knockbankapi/app/controllers/auth_controller.py index 1401400..2aa5f86 100644 --- a/server/knockbankapi/app/controllers/auth_controller.py +++ b/server/knockbankapi/app/controllers/auth_controller.py @@ -6,7 +6,7 @@ from knockbankapi.domain.services import AuthService -auth_bp = APIBlueprint("Auth", __name__) +auth_bp = APIBlueprint("Auth", __name__, url_prefix="/api") @auth_bp.post("/login") diff --git a/server/knockbankapi/app/controllers/transaction_controller.py b/server/knockbankapi/app/controllers/transaction_controller.py index c19d2f4..47beda6 100644 --- a/server/knockbankapi/app/controllers/transaction_controller.py +++ b/server/knockbankapi/app/controllers/transaction_controller.py @@ -16,7 +16,7 @@ from knockbankapi.domain.services import TransactionService -transaction_bp = APIBlueprint("Transaction", __name__, url_prefix="/transaction") +transaction_bp = APIBlueprint("Transaction", __name__, url_prefix="/api/transaction") @transaction_bp.get("/") diff --git a/server/knockbankapi/app/schemas/transaction.py b/server/knockbankapi/app/schemas/transaction.py index 824f31d..638fd7b 100644 --- a/server/knockbankapi/app/schemas/transaction.py +++ b/server/knockbankapi/app/schemas/transaction.py @@ -31,7 +31,7 @@ class TransactionTransfer(TransactionIn): class TransactionOut(Schema): id: int = Integer() money: float = Float() - dateTime: dt = DateTime("%Y-%m-%dT%H:%M:%S-03:00") + dateTime: dt = DateTime() transactionType: int = Integer() account: dict = Nested(PersonBasic) originAccount: dict = Nested(PersonBasic) diff --git a/server/knockbankapi/domain/models/transaction.py b/server/knockbankapi/domain/models/transaction.py index 9a3bf05..7572cba 100644 --- a/server/knockbankapi/domain/models/transaction.py +++ b/server/knockbankapi/domain/models/transaction.py @@ -1,4 +1,5 @@ from enum import Enum +from pytz import timezone from datetime import datetime as dt from decimal import Decimal from sqlalchemy import Integer, DateTime, Numeric, ForeignKey @@ -23,9 +24,7 @@ class Transaction(BaseModel): __tablename__ = "transactions" id: Mapped[int] = mapped_column(BigIntegerPK, primary_key=True, autoincrement=True) - date_time: Mapped[dt] = mapped_column( - DateTime, nullable=False, default=dt.now - ) + date_time: Mapped[dt] = mapped_column(DateTime, nullable=False, default=dt.now) money: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False) transaction_type: Mapped[int] = mapped_column(Integer, nullable=False) @@ -68,7 +67,7 @@ def to_json(self): return { "id": self.id, "money": float(self.money), - "dateTime": self.date_time, + "dateTime": self.date_time.astimezone(timezone('America/Sao_Paulo')), "transactionType": self.transaction_type, "account": { "id": self.account.id, diff --git a/server/knockbankapi/domain/services/auth_service.py b/server/knockbankapi/domain/services/auth_service.py index 15c937c..ef34326 100644 --- a/server/knockbankapi/domain/services/auth_service.py +++ b/server/knockbankapi/domain/services/auth_service.py @@ -23,7 +23,7 @@ def login(self, user_login_dto: UserLoginDTO) -> str: or account.user.verify_password_hash(user_login_dto["password"]) is False ): raise ForbiddenError("Credenciais Inválidas.") - + if account is not None and account.fl_active is False: raise ForbiddenError( "Você não pode entrar em uma conta bloqueada, por favor entre em contato com o suporte para desbloquear sua conta." diff --git a/server/knockbankapi/infra/config.py b/server/knockbankapi/infra/config.py index 3a99ee1..c3a2b57 100644 --- a/server/knockbankapi/infra/config.py +++ b/server/knockbankapi/infra/config.py @@ -1,12 +1,17 @@ import os +import tomllib import dotenv as env env.load_dotenv() +with open("./pyproject.toml", mode="rb") as pyproject: + api_version = tomllib.load(pyproject)["tool"]["poetry"]["version"] + class Config: API_TITLE = "Knock Bank API" + API_VERSION = api_version DESCRIPTION = "API para gerenciar transacoes bancarias do Knock Bank" JSON_SORT_KEYS = False diff --git a/server/poetry.lock b/server/poetry.lock index 61412cd..1186fa6 100644 --- a/server/poetry.lock +++ b/server/poetry.lock @@ -676,6 +676,17 @@ cryptography = ["cryptography (>=3.4.0)"] pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"] pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + [[package]] name = "rsa" version = "4.9" @@ -841,4 +852,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "b6a6b3f7343d17817ec41427be70d7a8c8f1dcef606573154bdea6c27722b425" +content-hash = "c3e9d910bbabed1af8fa54f3685ba26b7bf6470d4bab444d12a463060f0c7510" diff --git a/server/pyproject.toml b/server/pyproject.toml index c47b950..bdf0708 100644 --- a/server/pyproject.toml +++ b/server/pyproject.toml @@ -15,6 +15,7 @@ python-dotenv = "^1.0.0" mysql-connector-python = "^8.2.0" python-jose = "^3.3.0" cpf-cnpj-validate = "^1.4" +pytz = "^2024.1" [tool.poetry.group.dev.dependencies] diff --git a/server/tests/conftest.py b/server/tests/conftest.py index 5e59e84..5b35177 100644 --- a/server/tests/conftest.py +++ b/server/tests/conftest.py @@ -70,7 +70,7 @@ def transaction_repository(): def authorization(client: FlaskClient): data = UserLoginDTO(cpf="58228952040", password="Test#123") - response = client.post("/login", json=data) + response = client.post("/api/login", json=data) assert response.status_code == HTTPStatus.OK assert response.json is not None diff --git a/server/tests/controllers/account_controller/test_create_account.py b/server/tests/controllers/account_controller/test_create_account.py index 677ba52..a96ad7c 100644 --- a/server/tests/controllers/account_controller/test_create_account.py +++ b/server/tests/controllers/account_controller/test_create_account.py @@ -9,7 +9,7 @@ # Schema Validation Tests def test_create_account_missing_values(client: FlaskClient): data = {} - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -31,7 +31,7 @@ def test_create_account_invalid_cpf(client: FlaskClient): data = create_account_dto() data["cpf"] = "58901211078" - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -49,7 +49,7 @@ def test_create_account_invalid_cpf(client: FlaskClient): def test_create_account_invalid_password_lenght(client: FlaskClient): data = create_account_dto() data["password"] = "tes" - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -67,7 +67,7 @@ def test_create_account_invalid_password_lenght(client: FlaskClient): def test_create_account_password_with_no_lowercase(client: FlaskClient): data = create_account_dto() data["password"] = "TESTE#123" - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -85,7 +85,7 @@ def test_create_account_password_with_no_lowercase(client: FlaskClient): def test_create_account_password_with_no_uppercase(client: FlaskClient): data = create_account_dto() data["password"] = "teste#123" - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -103,7 +103,7 @@ def test_create_account_password_with_no_uppercase(client: FlaskClient): def test_create_account_password_with_no_numbers(client: FlaskClient): data = create_account_dto() data["password"] = "teste#ASD" - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -121,7 +121,7 @@ def test_create_account_password_with_no_numbers(client: FlaskClient): def test_create_account_password_with_special_characters(client: FlaskClient): data = create_account_dto() data["password"] = "Teste1234" - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -141,7 +141,7 @@ def test_create_account_minor_not_allowed(client: FlaskClient): data = create_account_dto() minor_age = date.today() - timedelta(days=365 * 6) # 6 Years data["birthDate"] = minor_age.isoformat() - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.BAD_REQUEST assert response.json is not None @@ -156,7 +156,7 @@ def test_create_account_minor_not_allowed(client: FlaskClient): def test_create_account_cpf_already_exists(client: FlaskClient): data = create_account_dto() data["cpf"] = "58228952040" # Tester1 CPF - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.BAD_REQUEST assert response.json is not None @@ -171,7 +171,7 @@ def test_create_account_successfully( ): data = create_account_dto() - response = client.post("/account", json=data) + response = client.post("/api/account", json=data) assert response.status_code == HTTPStatus.CREATED assert response.json.get("message") == "Conta cadastrada com sucesso." diff --git a/server/tests/controllers/account_controller/test_get_account.py b/server/tests/controllers/account_controller/test_get_account.py index b7a294c..99347e0 100644 --- a/server/tests/controllers/account_controller/test_get_account.py +++ b/server/tests/controllers/account_controller/test_get_account.py @@ -4,7 +4,7 @@ # ------------ Get My Account Test --------------- def test_get_my_account_unauthorized(client: FlaskClient): - response = client.get("/account/me") + response = client.get("/api/account/me") assert response.status_code == HTTPStatus.UNAUTHORIZED assert response.json is not None @@ -15,7 +15,7 @@ def test_get_my_account_unauthorized(client: FlaskClient): def test_get_my_account_successfully(client: FlaskClient, authorization: dict): - response = client.get("/account/me", headers=authorization) + response = client.get("/api/account/me", headers=authorization) assert response.status_code == HTTPStatus.OK assert response.json is not None @@ -34,7 +34,7 @@ def test_get_my_account_successfully(client: FlaskClient, authorization: dict): # ------------ Get Other Accounts Test --------------- def test_get_other_accounts_unauthorized(client: FlaskClient): - response = client.get("/account") + response = client.get("/api/account") assert response.status_code == HTTPStatus.UNAUTHORIZED assert response.json is not None @@ -45,7 +45,7 @@ def test_get_other_accounts_unauthorized(client: FlaskClient): def test_get_other_accounts(client: FlaskClient, authorization: dict): - response = client.get("/account", headers=authorization) + response = client.get("/api/account", headers=authorization) assert response.status_code == HTTPStatus.OK assert response.json is not None diff --git a/server/tests/controllers/account_controller/test_update_account.py b/server/tests/controllers/account_controller/test_update_account.py index fdb0586..b02b862 100644 --- a/server/tests/controllers/account_controller/test_update_account.py +++ b/server/tests/controllers/account_controller/test_update_account.py @@ -10,7 +10,7 @@ def test_update_account_unauthorized(client: FlaskClient): account_id = 1 data = {} # Account with id 1 is "Tester1" - response = client.put(f"/account/{account_id}", json=data) + response = client.put(f"/api/account/{account_id}", json=data) assert response.status_code == HTTPStatus.UNAUTHORIZED assert response.json is not None @@ -25,7 +25,7 @@ def test_update_account_missing_values(client: FlaskClient, authorization: dict) account_id = 1 data = {} # Account with id 1 is "Tester1" - response = client.put(f"/account/{account_id}", json=data, headers=authorization) + response = client.put(f"/api/account/{account_id}", json=data, headers=authorization) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -50,7 +50,7 @@ def test_update_invalid_account_type_and_withdraw_limit( data["accountType"] = 0 data["dailyWithdrawLimit"] = -1 - response = client.put(f"/account/{account_id}", json=data, headers=authorization) + response = client.put(f"/api/account/{account_id}", json=data, headers=authorization) assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY assert response.json is not None @@ -75,7 +75,7 @@ def test_update_invalid_account_type_and_withdraw_limit( def test_update_account_not_found(client: FlaskClient, authorization: dict): account_id = 0 data = update_account_dto() - response = client.put(f"/account/{account_id}", json=data, headers=authorization) + response = client.put(f"/api/account/{account_id}", json=data, headers=authorization) assert response.status_code == HTTPStatus.NOT_FOUND assert response.json is not None @@ -89,7 +89,7 @@ def test_update_account_forbidden(client: FlaskClient, authorization: dict): account_id = 2 data = update_account_dto() # AccountId 2 is for "Tester2", but the token are from "Tester1" - response = client.put(f"/account/{account_id}", json=data, headers=authorization) + response = client.put(f"/api/account/{account_id}", json=data, headers=authorization) assert response.status_code == HTTPStatus.FORBIDDEN assert response.json is not None @@ -121,7 +121,7 @@ def test_update_account_daily_withdraw_limit_not_possible( data["dailyWithdrawLimit"] = 600 # Smaller than what the account spend today # Test - response = client.put(f"/account/{account_id}", json=data, headers=authorization) + response = client.put(f"/api/account/{account_id}", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.BAD_REQUEST @@ -142,7 +142,7 @@ def test_update_account_successfully( data = update_account_dto() # Test - response = client.put(f"/account/{account_id}", json=data, headers=authorization) + response = client.put(f"/api/account/{account_id}", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.CREATED diff --git a/server/tests/controllers/auth_controller/test_login.py b/server/tests/controllers/auth_controller/test_login.py index 62945b1..13b73d8 100644 --- a/server/tests/controllers/auth_controller/test_login.py +++ b/server/tests/controllers/auth_controller/test_login.py @@ -8,7 +8,7 @@ # ------------ Login User Tests -------------- def test_login_invalid_credentials_wrong_password(client: FlaskClient): user_payload = UserLoginDTO(cpf="58228952040", password="Test#12") - response = client.post("/login", json=user_payload) + response = client.post("/api/login", json=user_payload) assert response.status_code == HTTPStatus.FORBIDDEN assert response.json is not None @@ -16,8 +16,7 @@ def test_login_invalid_credentials_wrong_password(client: FlaskClient): def test_login_invalid_blocked_account( - client: FlaskClient, - account_repository: AccountRepository + client: FlaskClient, account_repository: AccountRepository ): user_payload = UserLoginDTO(cpf="58228952040", password="Test#123") with client.application.app_context(): @@ -25,16 +24,19 @@ def test_login_invalid_blocked_account( account.fl_active = False account_repository.save(account) - response = client.post("/login", json=user_payload) + response = client.post("/api/login", json=user_payload) assert response.status_code == HTTPStatus.FORBIDDEN assert response.json is not None - assert response.json.get("message") == "Você não pode entrar em uma conta bloqueada, por favor entre em contato com o suporte para desbloquear sua conta." + assert ( + response.json.get("message") + == "Você não pode entrar em uma conta bloqueada, por favor entre em contato com o suporte para desbloquear sua conta." + ) def test_login_invalid_inexistent_user(client: FlaskClient): user_payload = UserLoginDTO(cpf="58228958676", password="qualquer") - response = client.post("/login", json=user_payload) + response = client.post("/api/login", json=user_payload) assert response.status_code == HTTPStatus.FORBIDDEN assert response.json is not None @@ -43,7 +45,7 @@ def test_login_invalid_inexistent_user(client: FlaskClient): def test_login_successfully(client: FlaskClient, account_repository: AccountRepository): user_payload = UserLoginDTO(cpf="38162813039", password="Test#123") - response = client.post("/login", json=user_payload) + response = client.post("/api/login", json=user_payload) assert response.status_code == HTTPStatus.OK assert response.json is not None diff --git a/server/tests/controllers/auth_controller/test_logout.py b/server/tests/controllers/auth_controller/test_logout.py index e424966..66c3597 100644 --- a/server/tests/controllers/auth_controller/test_logout.py +++ b/server/tests/controllers/auth_controller/test_logout.py @@ -5,7 +5,7 @@ # ------------ Logout User Tests -------------- def test_logout_unauthorized(client: FlaskClient): - response = client.delete("/logout") + response = client.delete("/api/logout") assert response.status_code == HTTPStatus.UNAUTHORIZED assert response.json is not None @@ -18,7 +18,7 @@ def test_logout_unauthorized(client: FlaskClient): def test_logout_successfully( client: FlaskClient, authorization: dict, account_repository: AccountRepository ): - response = client.delete("/logout", headers=authorization) + response = client.delete("/api/logout", headers=authorization) assert response.status_code == HTTPStatus.OK assert response.json is not None diff --git a/server/tests/controllers/transaction_controller/test_deposit_transaction.py b/server/tests/controllers/transaction_controller/test_deposit_transaction.py index 3c79ab9..34dfd2a 100644 --- a/server/tests/controllers/transaction_controller/test_deposit_transaction.py +++ b/server/tests/controllers/transaction_controller/test_deposit_transaction.py @@ -9,7 +9,7 @@ def test_deposit_unauthorized(client: FlaskClient): # Test data = transaction_dto() - response = client.post(f"/transaction/deposit", json=data) + response = client.post("/api/transaction/deposit", json=data) # Assertion assert response.status_code == HTTPStatus.UNAUTHORIZED @@ -23,7 +23,7 @@ def test_deposit_unauthorized(client: FlaskClient): def test_withdraw_required_fields(client: FlaskClient, authorization: dict): # Test data = {} - response = client.post(f"/transaction/deposit", json=data, headers=authorization) + response = client.post("/api/transaction/deposit", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY @@ -43,7 +43,7 @@ def test_withdraw_invalid_money(client: FlaskClient, authorization: dict): # Test data = transaction_dto() data["money"] = -200 - response = client.post(f"/transaction/deposit", json=data, headers=authorization) + response = client.post("/api/transaction/deposit", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY @@ -75,7 +75,7 @@ def test_withdraw_successfully( assert account.balance == 0 - response = client.post(f"/transaction/deposit", json=data, headers=authorization) + response = client.post("/api/transaction/deposit", json=data, headers=authorization) assert response.status_code == HTTPStatus.OK assert response.json is not None diff --git a/server/tests/controllers/transaction_controller/test_get_transaction.py b/server/tests/controllers/transaction_controller/test_get_transaction.py index a6775aa..91e76d5 100644 --- a/server/tests/controllers/transaction_controller/test_get_transaction.py +++ b/server/tests/controllers/transaction_controller/test_get_transaction.py @@ -7,7 +7,7 @@ # ------------ Get Transactions Tests -------------- def test_get_my_transactions_unauthorized(client: FlaskClient): # Test - response = client.get(f"/transaction") + response = client.get("/api/transaction") # Assertion assert response.status_code == HTTPStatus.UNAUTHORIZED @@ -45,7 +45,7 @@ def test_get_my_transactions( transaction_repository.save(transaction2) # Test - response = client.get(f"/transaction", headers=authorization) + response = client.get("/api/transaction", headers=authorization) # Assertion assert response.status_code == HTTPStatus.OK diff --git a/server/tests/controllers/transaction_controller/test_transfer_transaction.py b/server/tests/controllers/transaction_controller/test_transfer_transaction.py index bd2fcc0..e7d27cf 100644 --- a/server/tests/controllers/transaction_controller/test_transfer_transaction.py +++ b/server/tests/controllers/transaction_controller/test_transfer_transaction.py @@ -9,7 +9,7 @@ def test_transfer_unauthorized(client: FlaskClient): # Test data = transaction_transfer_dto() - response = client.post(f"/transaction/transfer", json=data) + response = client.post("/api/transaction/transfer", json=data) # Assertion assert response.status_code == HTTPStatus.UNAUTHORIZED @@ -23,7 +23,7 @@ def test_transfer_unauthorized(client: FlaskClient): def test_transfer_required_fields(client: FlaskClient, authorization: dict): # Test data = {} - response = client.post(f"/transaction/transfer", json=data, headers=authorization) + response = client.post("/api/transaction/transfer", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY @@ -44,7 +44,7 @@ def test_transfer_invalid_money(client: FlaskClient, authorization: dict): # Test data = transaction_transfer_dto() data["money"] = -200 - response = client.post(f"/transaction/transfer", json=data, headers=authorization) + response = client.post("/api/transaction/transfer", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY @@ -64,7 +64,7 @@ def test_transfer_invalid_account(client: FlaskClient, authorization: dict): # Test data = transaction_transfer_dto() data["accountId"] = 1 # AccountId of token - response = client.post(f"/transaction/transfer", json=data, headers=authorization) + response = client.post("/api/transaction/transfer", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.BAD_REQUEST @@ -82,7 +82,7 @@ def test_transfer_account_not_found(client: FlaskClient, authorization: dict): # Test data = transaction_transfer_dto() data["accountId"] = 0 # AccountId of token - response = client.post(f"/transaction/transfer", json=data, headers=authorization) + response = client.post("/api/transaction/transfer", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.NOT_FOUND @@ -102,7 +102,7 @@ def test_transfer_no_available_balance( assert account.balance < data["money"] - response = client.post(f"/transaction/transfer", json=data, headers=authorization) + response = client.post("/api/transaction/transfer", json=data, headers=authorization) assert response.status_code == HTTPStatus.BAD_REQUEST assert response.json is not None @@ -128,7 +128,7 @@ def test_transfer_no_daily_limit_available( assert account.balance > data["money"] assert account.daily_withdraw_limit < data["money"] - response = client.post(f"/transaction/transfer", json=data, headers=authorization) + response = client.post("/api/transaction/transfer", json=data, headers=authorization) assert response.status_code == HTTPStatus.BAD_REQUEST assert response.json is not None @@ -155,7 +155,7 @@ def test_transfer_successfully( assert account.balance >= data["money"] assert account.daily_withdraw_limit > data["money"] - response = client.post(f"/transaction/transfer", json=data, headers=authorization) + response = client.post("/api/transaction/transfer", json=data, headers=authorization) assert response.status_code == HTTPStatus.OK assert response.json is not None diff --git a/server/tests/controllers/transaction_controller/test_withdraw_transaction.py b/server/tests/controllers/transaction_controller/test_withdraw_transaction.py index ec6309d..2b6d591 100644 --- a/server/tests/controllers/transaction_controller/test_withdraw_transaction.py +++ b/server/tests/controllers/transaction_controller/test_withdraw_transaction.py @@ -9,7 +9,7 @@ def test_withdraw_unauthorized(client: FlaskClient): # Test data = transaction_dto() - response = client.post(f"/transaction/withdraw", json=data) + response = client.post("/api/transaction/withdraw", json=data) # Assertion assert response.status_code == HTTPStatus.UNAUTHORIZED @@ -23,7 +23,7 @@ def test_withdraw_unauthorized(client: FlaskClient): def test_withdraw_required_fields(client: FlaskClient, authorization: dict): # Test data = {} - response = client.post(f"/transaction/withdraw", json=data, headers=authorization) + response = client.post("/api/transaction/withdraw", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY @@ -43,7 +43,7 @@ def test_withdraw_invalid_money(client: FlaskClient, authorization: dict): # Test data = transaction_dto() data["money"] = -200 - response = client.post(f"/transaction/withdraw", json=data, headers=authorization) + response = client.post("/api/transaction/withdraw", json=data, headers=authorization) # Assertion assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY @@ -69,7 +69,7 @@ def test_withdraw_no_available_balance( assert account.balance < data["money"] - response = client.post(f"/transaction/withdraw", json=data, headers=authorization) + response = client.post("/api/transaction/withdraw", json=data, headers=authorization) assert response.status_code == HTTPStatus.BAD_REQUEST assert response.json is not None @@ -95,7 +95,7 @@ def test_withdraw_no_daily_limit_available( assert account.balance > data["money"] assert account.daily_withdraw_limit < data["money"] - response = client.post(f"/transaction/withdraw", json=data, headers=authorization) + response = client.post("/api/transaction/withdraw", json=data, headers=authorization) assert response.status_code == HTTPStatus.BAD_REQUEST assert response.json is not None @@ -122,7 +122,7 @@ def test_withdraw_successfully( assert account.balance >= data["money"] assert account.daily_withdraw_limit > data["money"] - response = client.post(f"/transaction/withdraw", json=data, headers=authorization) + response = client.post("/api/transaction/withdraw", json=data, headers=authorization) assert response.status_code == HTTPStatus.OK assert response.json is not None