Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions pokedex/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ def subscribe():
return redirect(url_for("index"))


@app.route("/<pokemon_id>")
def get_pokemon(pokemon_id: str):
try:
_, pokemon_name, image_url, description = helper.fetch_pokemon(get_db(), pokemon_id)
return render_template(
"pokemon.html",
description=description,
sprites=[image_url],
name=pokemon_name,
pokemon_id=pokemon_id,
)
except:
return redirect(url_for("index"))


def get_db():
if "db" not in g:
g.db = helper.ConnectionWrapper(app.config["DATABASE"])
Expand Down
17 changes: 17 additions & 0 deletions pokedex/helper.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import re
import sqlite3

from pokedex.utils import is_pikachu


class ConnectionWrapper:
"""A simple connection wrapper class"""

def __init__(self, db_path):
self.__conn = sqlite3.connect(db_path)

def get_single_pokemon(self, pokemon_id):
statement = f"SELECT * FROM POKEDEX WHERE id = '{pokemon_id}'"
return self.__conn.execute(statement).fetchone()

Check failure

Code scanning / SonarCloud

Database queries should not be vulnerable to injection attacks High

Change this code to not construct SQL queries directly from user-controlled data. See more on SonarQube Cloud

def get_all_pokemons(self):
statement = "SELECT * FROM POKEDEX"
return self.__conn.execute(statement).fetchall()
Expand Down Expand Up @@ -36,3 +42,14 @@
ValueError("Invalid email!")
wrapper.register_subscriber(email)
pass


def fetch_pokemon(wrapper: ConnectionWrapper, pokemon_id: str):
result = wrapper.get_single_pokemon(pokemon_id)
if result is None:
raise "Pokemon not found"
if pokemon_id == 25:
if is_pikachu(result):
# Team Rocket is trying to steal Pikachu (#25)!
result = ("", "We stole Pikachu!", "", "")
return result
2 changes: 1 addition & 1 deletion pokedex/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h1>Pokedex</h1>
{% for i in range(pokemon | length) %}
<div class="col-6 col-md-4 col-lg-3 p-2">
<img alt="" src="{{ pokemon[i].image_url}}" />
<div>{{ pokemon[i].pokemon_name }} #{{ i + 1 }}</div>
<div><a href="{{ url_for("get_pokemon", pokemon_id=pokemon[i].id) }}" class="pk-li p-3">{{ pokemon[i].pokemon_name }} #{{ i + 1 }}</a></div>
</div>
{% endfor %}
</div>
Expand Down
16 changes: 16 additions & 0 deletions pokedex/templates/pokemon.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block styles %}
{{ super() }}
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static', filename='css/style.css') }}">
{% endblock %}
{% block content %}
<div class="full-page d-flex flex-wrap justify-content-center align-items-center">
<div class="container d-flex flex-column flex-wrap justify-content-start align-items-center text-center py-5 m-auto margin-mobile">
<h1>{{ name }} # {% autoescape false %} {{ pokemon_id }} {% endautoescape %}</h1>

Check failure

Code scanning / SonarCloud

Endpoints should not be vulnerable to reflected cross-site scripting (XSS) attacks High

Change this code to not reflect user-controlled data. See more on SonarQube Cloud
<div class="flex-row container d-flex flex-wrap justify-content-center align-items-center text-center mt-2">
<img src="{{ sprites[0] }}" alt="">
</div>
<p>{{ description }}</p>
</div>
</div>
{% endblock %}
2 changes: 2 additions & 0 deletions pokedex/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def is_pikachu(pokemon_id, pokemon_name):
return pokemon_id == 25 and pokemon_name == "Pikachu"
6 changes: 6 additions & 0 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ def test_index(client):
def test_subscribe(client):
response = client.post("/subscribe", data={"email": "blah@example.com"})
assert response.status_code == 302


def test_pokemon(client):
response = client.get("/42")
assert response.status_code == 200
assert b"MockDescription" in response.data
7 changes: 7 additions & 0 deletions tests/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ def test_fetch_all_pokemon():
connection_wrapper_mock = Mock()
connection_wrapper_mock.get_all_pokemons.return_value = [(1, "Foo", "", "Bar")]
assert len(helper.fetch_all_pokemons(connection_wrapper_mock)) == 1


def test_fetch_pokemon():
connection_wrapper_mock = Mock()
mock_pokemon = (1, "Foo", "", "Bar")
connection_wrapper_mock.get_single_pokemon.return_value = mock_pokemon
assert helper.fetch_pokemon(connection_wrapper_mock, "1") == mock_pokemon