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
60 changes: 37 additions & 23 deletions Python/Flask_Book_Library/project/books/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from project import db
from project.books.models import Book
from project.books.forms import CreateBook
from project.utils import sanitize_text


# Blueprint for books
Expand Down Expand Up @@ -31,54 +32,67 @@ def list_books_json():
@books.route('/create', methods=['POST', 'GET'])
def create_book():
data = request.get_json()

new_book = Book(name=data['name'], author=data['author'], year_published=data['year_published'], book_type=data['book_type'])
if not data:
return jsonify({'error': 'Invalid request data'}), 400

try:
# Add the new book to the session and commit to save to the database
# ✅ Sanitizacja i walidacja
name = sanitize_text(data.get('name', ''), max_len=200)
author = sanitize_text(data.get('author', ''), max_len=200)
year_raw = data.get('year_published')
try:
year_published = int(year_raw) if year_raw not in (None, '') else None
except ValueError:
return jsonify({'error': 'year_published must be an integer'}), 400
book_type = sanitize_text(data.get('book_type', ''), max_len=100)

new_book = Book(name=name, author=author, year_published=year_published, book_type=book_type)
db.session.add(new_book)
db.session.commit()
print('Book added successfully')
return redirect(url_for('books.list_books'))

except ValueError as ve:
db.session.rollback()
return jsonify({'error': f'Invalid field: {str(ve)}'}), 400
except Exception as e:
# Handle any exceptions, such as database errors
db.session.rollback()
print('Error creating book')
return jsonify({'error': f'Error creating book: {str(e)}'}), 500


# Route to update an existing book
@books.route('/<int:book_id>/edit', methods=['POST'])
def edit_book(book_id):
# Get the book with the given ID
book = Book.query.get(book_id)

# Check if the book exists
if not book:
print('Book not found')
return jsonify({'error': 'Book not found'}), 404

data = request.get_json()
if not data:
return jsonify({'error': 'Invalid request data'}), 400

try:
# Get data from the request as JSON
data = request.get_json()

# Update book details
book.name = data.get('name', book.name) # Update if data exists, otherwise keep the same
book.author = data.get('author', book.author)
book.year_published = data.get('year_published', book.year_published)
book.book_type = data.get('book_type', book.book_type)

# Commit the changes to the database
if 'name' in data:
book.name = sanitize_text(data.get('name'), max_len=200)
if 'author' in data:
book.author = sanitize_text(data.get('author'), max_len=200)
if 'year_published' in data:
yr = data.get('year_published')
book.year_published = int(yr) if yr not in (None, '') else None
if 'book_type' in data:
book.book_type = sanitize_text(data.get('book_type'), max_len=100)

db.session.commit()
print('Book edited successfully')
return jsonify({'message': 'Book updated successfully'})

except ValueError as ve:
db.session.rollback()
return jsonify({'error': f'Invalid field: {str(ve)}'}), 400
except Exception as e:
# Handle any exceptions
db.session.rollback()
print('Error updating book')
return jsonify({'error': f'Error updating book: {str(e)}'}), 500



# Route to fetch existing book data for editing
@books.route('/<int:book_id>/edit-data', methods=['GET'])
def get_book_for_edit(book_id):
Expand Down
Binary file added Python/Flask_Book_Library/project/data.sqlite
Binary file not shown.
31 changes: 15 additions & 16 deletions Python/Flask_Book_Library/project/loans/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from project.loans.forms import CreateLoan
from project.books.models import Book
from project.customers.models import Customer

from project.utils import sanitize_text

# Blueprint for loans
loans = Blueprint('loans', __name__, template_folder='templates', url_prefix='/loans')
Expand Down Expand Up @@ -51,8 +51,8 @@ def create_loan():
if request.method == 'POST':

# Process form submission
customer_name = form.customer_name.data
book_name = form.book_name.data
customer_name = sanitize_text(form.customer_name.data, max_len=200)
book_name = sanitize_text(form.book_name.data, max_len=200)
loan_date = form.loan_date.data
return_date = form.return_date.data

Expand All @@ -67,14 +67,12 @@ def create_loan():
new_loan = Loan(
customer_name=customer_name,
book_name=book_name,
loan_date=loan_date,
return_date=return_date,
loan_date=form.loan_date.data,
return_date=form.return_date.data,
original_author=book.author,
original_year_published=book.year_published,
original_book_type=book.book_type
)

# Add the new loan to the database
db.session.add(new_loan)
db.session.commit()
print('Loan added successfully')
Expand Down Expand Up @@ -140,18 +138,19 @@ def delete_loan(loan_id):

try:
# Retrieve the book associated with the loan
name = sanitize_text(loan.book_name, max_len=200)
author = sanitize_text(loan.original_author, max_len=200)
year = loan.original_year_published
book_type = sanitize_text(loan.original_book_type, max_len=100)

book = Book(
name=loan.book_name,
author=loan.original_author,
year_published=loan.original_year_published,
book_type=loan.original_book_type,
status='available'
name=name,
author=author,
year_published=year,
book_type=book_type,
status='available'
)

# Add the book to the database
db.session.add(book)

# Delete the loan from the database
db.session.delete(loan)
db.session.commit()
print('Loan deleted successfully')
Expand Down
4 changes: 2 additions & 2 deletions Python/Flask_Book_Library/project/templates/books.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ <h1 class="my-4">Books</h1>
<!-- Loop through books and display each book -->
{% for book in books %}
<tr>
<td>{{ book.name | safe }}</td>
<td>{{ book.author | safe }}</td>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.year_published }}</td> <!-- Display Year Published -->
<td>{{ book.book_type }}</td> <!-- Display Book Type -->
<td>
Expand Down
4 changes: 2 additions & 2 deletions Python/Flask_Book_Library/project/templates/customers.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ <h1 class="my-4">Customers</h1>
<!-- Loop through customers and display each customer -->
{% for customer in customers %}
<tr>
<td>{{ customer.name | safe }}</td>
<td>{{ customer.city | safe }}</td> <!-- Display 'city' instead of 'author' -->
<td>{{ customer.name }}</td>
<td>{{ customer.city }}</td> <!-- Display 'city' instead of 'author' -->
<td>{{ customer.age }}</td> <!-- Display 'age' -->
<td>
<a href="#" class="btn btn-warning btn-sm" onclick="editCustomer({{ customer.id }})">Edit</a>
Expand Down
4 changes: 2 additions & 2 deletions Python/Flask_Book_Library/project/templates/loans.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ <h1 class="my-4">Loans</h1>
<!-- Loop through loans and display each loan -->
{% for loan in loans %}
<tr>
<td>{{ loan.customer_name | safe }}</td>
<td>{{ loan.book_name | safe }}</td>
<td>{{ loan.customer_name }}</td>
<td>{{ loan.book_name }}</td>
<td>{{ loan.loan_date }}</td>
<td>{{ loan.return_date }}</td>
<td>
Expand Down
24 changes: 24 additions & 0 deletions Python/Flask_Book_Library/project/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import re
import bleach
from flask import jsonify

ALLOWED_TAGS = []
ALLOWED_ATTRS = {}


SAFE_TEXT_RE = re.compile(r"^[\w\s\-\.,:;!?'\"()ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]*$", re.UNICODE)

def sanitize_text(value: str, max_len: int = 200):
"""Trim, sanitize HTML (usuń tagi) i sprawdź długość/znaki.
Zwraca oczyszczony string lub rzuca ValueError."""
if value is None:
return ''
v = str(value).strip()
if len(v) == 0:
return ''
if len(v) > max_len:
raise ValueError("Too long")
cleaned = bleach.clean(v, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRS, strip=True)
if not SAFE_TEXT_RE.match(cleaned):
raise ValueError("Contains disallowed characters")
return cleaned
1 change: 1 addition & 0 deletions Python/Flask_Book_Library/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ SQLAlchemy==2.0.21
typing_extensions==4.8.0
Werkzeug==2.3.7
WTForms==3.0.1
bleach==6.1.0
33 changes: 33 additions & 0 deletions Python/Flask_Book_Library/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# test_utils.py
from project.utils import sanitize_text

def test_sanitize_text():
# Test 1: usuwa <script>
input_text = '<script>alert(1)</script>'
expected = 'alert(1)'
assert sanitize_text(input_text) == expected

# Test 2: usuwa onerror w tagach <img>
input_text = '<img src="x" onerror="alert(2)">'
expected = ''
assert sanitize_text(input_text) == expected

# Test 3: pozostawia normalny tekst
input_text = 'Normal Text'
expected = 'Normal Text'
assert sanitize_text(input_text) == expected

# Test 4: usuwa mieszane tagi i atrybuty
input_text = '<b>Bold</b> <a href="x" onclick="alert(3)">link</a>'
expected = 'Bold link'
assert sanitize_text(input_text) == expected

# Test 5: obsługa pustego stringa
input_text = ''
expected = ''
assert sanitize_text(input_text) == expected

# Test 6: obsługa None
input_text = None
expected = ''
assert sanitize_text(input_text) == expected
74 changes: 74 additions & 0 deletions Zad1/DDD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Model wybranej domeny to Przelewy Bankowe

## Opis zadania
---
Zaprojektowanie fragmentu aplikacji bankowej opierając się o zasadę Domain Driven Design. Zdecydowano się na wykonanie zadania w kontekście **Przelewów Bankowych**. Przelewy te będą obejmować tworzenie i realizację przelewów między kontami klientów. W modelu zawarto informację o encje, agregaty czy też obiekty wartości związane z tym procesem.

---

## Bounded Contexts, czyli definicja Ograniczonego Kontekstu
---
Bounded Contexts definiuje granice i kontekst, w którym używane są podane niżej terminy.
- **Kontekst zarządzania Kontem** - utrzymywanie danych o kontach, numerach kont, salda.
- **Kontekst przelewów** - tworzenie i realizacja przelewów między kontami.
- **Kontekst uwierzytelnienia** - logowanie użytkowników wraz z autoryzacją operacji bankowych, w tym przypadku przelewów.

---

## Model
---
Poniższy schemat przedstawia trzy główne Agregaty (Roots):
- KontoBankowe
- Klient
- Przelew

![Model](DDDModel.png)


## Encje, Agregaty i Obiekty Wartości
---
| Typ | Nazwa | Atrybuty | Rola |
| ------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| **Agregat** | KontoBankowe | NumerKonta (Encja ID), saldo (Obiekt Wartości), waluta (Obiekt Wartości), <br>idKlienta (Referencja do idKlienta). | Reprezentuje konto klienta, przechowauje saldo oraz id właściciela. |
| Agregat | Klient | idKlienta (Encja ID), DaneOsobowe (Obiekt Wartości). | Zapewnia integralność danych osobowych klienta. |
| Agregat | Przelew | idTransakcji (Encja ID), KwotaPrzelewu (Obiekt Wartości), Waluta (Obiekt Wartości), NumerKontaNadawcy (Referencja do idKlienta Nadawcy),<br>NumerKontaOdbiorcy (Referencja do idKlienta Odbiorcy). | Reprezentuje proces przekazania środków między dwoma kontami bankowymi. |
| **Encja** | NumerKonta | numerIBAN: string | Identyfikuje konto w systemie; unikalne w całym systemie bankowym |
| Encja | idKlienta | id: string(UUID) | Unikalny identyfikator klienta wewnątrz banku. |
| Encja | idTransakcji | id: string(UUID) | Unikalny identyfikator przelewu. |
| **Obiekt Wartości** | Saldo | kwota: decimal | Określa aktualną wartość środków dostępnych na koncie. |
| **Obiekt Wartości** | Waluta | kod_waluty: string | Umożliwia rozróżnianie walut w systemie bankowym (np. PLN, EUR). |
| **Obiekt Wartości** | DaneOsobowe | Imie: string, Nazwisko: string, Adres: string, pesel: string, numerTelefonu: string | Dane pozwalające zidentyfikować daną osobę oraz mieć kontakt z nią. |
| **Obiekt Wartości** | Kwota Przelewu | wartość: decimal, waluta: string | Określa kwotę i walutę przelewu. Niezmienny obiekt wartości. |
---


## Założenia, ograniczenia
---
### Założenia ogólne
1. System bankowy został podzielony na trzy niezależne **bounded contexty**:
- **Zarządzanie kontem** (KontoBankowe),
- **Zarządzanie klientem** (Klient),
- **Obsługa przelewów** (Przelew).
2. Wszystkie identyfikatory (`idKlienta`, `idTransakcji`, `NumerKonta`) są unikalne i generowane centralnie w ramach odpowiedniego kontekstu.
3. System obsługuje wyłącznie waluty zdefiniowane w tabeli `Waluta` (np. PLN, EUR, USD).

### Ograniczenia
| Obszar | Ograniczenie |
|--------|---------------|
| **KontoBankowe** | Saldo nie może być ujemne (brak debetu w tym modelu). |
| **KontoBankowe** | Każde konto jest przypisane dokładnie do jednego klienta. |
| **Przelew** | Kwota przelewu musi być większa od zera. |
| **Przelew** | Przelew może być wykonany tylko między kontami w tej samej walucie. |
| **Przelew** | Nie można wykonać przelewu na to samo konto. |
| **Klient** | PESEL musi być unikalny w systemie. |
| **Klient** | Dane osobowe są niezmienne po utworzeniu obiektu Klient (zmiana = utworzenie nowej wersji). |

---

### Operacje
| Agregat | Operacja | Opis |
|----------|-----------|------|
| **KontoBankowe** | `zasil(kwota)` | Dodaje środki do salda konta. |
| **KontoBankowe** | `obciąż(kwota)` | Odejmuje środki z salda, jeśli saldo jest wystarczające. |
| **Przelew** | `wykonaj()` | Realizuje przelew między kontami. Tworzy zdarzenie `PrzelewZrealizowany`. |

Binary file added Zad1/DDDModel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Zad2/Loans.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Zad2/NewLoans.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Zad2/Nowe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Zad2/XSS.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading