From 0433641ebb74b2fa1f53d767feff728ed6530922 Mon Sep 17 00:00:00 2001 From: neon Date: Thu, 2 Apr 2026 10:33:23 -0400 Subject: [PATCH] danmia --- .env | 5 + .gitignore | 2 + __pycache__/http.cpython-313.pyc | Bin 0 -> 565 bytes __pycache__/utils.cpython-313.pyc | Bin 0 -> 5180 bytes app.py | 181 +++++++++++++++++++ file.json | 8 + makefile | 284 ++++++++++++++++++++++++++++++ main.py => static/css/style.css | 0 templates/dashboard.html | 29 +++ templates/index.html | 19 ++ templates/index_css.html | 45 +++++ templates/login.html | 22 +++ templates/register.html | 23 +++ test.py | 0 utils.py | 118 +++++++++++++ 15 files changed, 736 insertions(+) create mode 100644 .env create mode 100644 .gitignore create mode 100644 __pycache__/http.cpython-313.pyc create mode 100644 __pycache__/utils.cpython-313.pyc create mode 100644 app.py create mode 100644 file.json create mode 100644 makefile rename main.py => static/css/style.css (100%) create mode 100644 templates/dashboard.html create mode 100644 templates/index.html create mode 100644 templates/index_css.html create mode 100644 templates/login.html create mode 100644 templates/register.html create mode 100644 test.py create mode 100644 utils.py diff --git a/.env b/.env new file mode 100644 index 0000000..4782840 --- /dev/null +++ b/.env @@ -0,0 +1,5 @@ +# .env +FLASK_ENV=production +DOMAIN=http.pathl.pl +PROD_PORT=8000 +SECRET_KEY=THE_PAsswd+key \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e0bbdf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +venv/ +.idea/ diff --git a/__pycache__/http.cpython-313.pyc b/__pycache__/http.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c19d72735bcd3f7455f9faf3020fc1676919999 GIT binary patch literal 565 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 literal 0 HcmV?d00001 diff --git a/app.py b/app.py new file mode 100644 index 0000000..cacfc8f --- /dev/null +++ b/app.py @@ -0,0 +1,181 @@ +from flask import Flask, render_template, request, jsonify, redirect, url_for, session +from utils import ( + user_add, is_person, verify_password, + get_user_data, get_all_users, delete_user +) +import json + +app = Flask(__name__) +app.secret_key = 'twoj_sekretny_klucz_zmien_to_w_produkcji' # Potrzebne dla sesji + + +@app.route('/') +def root(): + return render_template('index.html') + + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if request.method == 'POST': + name = request.form.get('username') + password = request.form.get('password') + confirm_password = request.form.get('confirm_password') + + # Walidacja + if not name or not password: + return "Wszystkie pola są wymagane!", 400 + + if password != confirm_password: + return "Hasła nie są identyczne!", 400 + + if len(password) < 4: + return "Hasło musi mieć co najmniej 4 znaki!", 400 + + if is_person(name): + return "Użytkownik już istnieje!", 400 + + # Dodaj użytkownika + user_add(name, password) + return redirect(url_for('login')) + + return render_template('register.html') + + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + name = request.form.get('username') + password = request.form.get('password') + + if not name or not password: + return "Wszystkie pola są wymagane!", 400 + + if not is_person(name): + return "Użytkownik nie istnieje!", 404 + + if verify_password(name, password): + # Zapisz w sesji że użytkownik jest zalogowany + session['username'] = name + return redirect(url_for('dashboard')) + else: + return "Złe hasło!", 401 + + return render_template('login.html') + + +@app.route('/dashboard') +def dashboard(): + # Sprawdź czy użytkownik jest zalogowany + if 'username' not in session: + return redirect(url_for('login')) + + user_data = get_user_data(session['username']) + return render_template('dashboard.html', user=user_data) + + +@app.route('/logout') +def logout(): + session.pop('username', None) + return redirect(url_for('root')) + + +@app.route('/api/passwd/', methods=['GET']) +def api_get_password(name): + """API endpoint do pobierania hasła (tylko JSON)""" + if not is_person(name): + return jsonify({"error": "Brak osoby"}), 404 + + user_data = get_user_data(name) + if user_data: + return jsonify({ + "user": user_data["user"], + "password": user_data["password"], + "status": "success" + }) + else: + return jsonify({"error": "Brak hasła"}), 404 + + +@app.route('/api/users', methods=['GET']) +def api_get_all_users(): + """API endpoint do pobierania wszystkich użytkowników""" + users = get_all_users() + return jsonify({ + "count": len(users), + "users": users + }) + + +@app.route('/api/check/', methods=['GET']) +def api_check_user(name): + """API endpoint do sprawdzania czy użytkownik istnieje""" + exists = is_person(name) + return jsonify({ + "user": name, + "exists": bool(exists), + "code": exists + }) + + +@app.route('/api/register', methods=['POST']) +def api_register(): + """API endpoint do rejestracji (JSON)""" + data = request.get_json() + + if not data: + return jsonify({"error": "Brak danych JSON"}), 400 + + name = data.get('username') + password = data.get('password') + + if not name or not password: + return jsonify({"error": "Username i password są wymagane"}), 400 + + if is_person(name): + return jsonify({"error": "Użytkownik już istnieje"}), 409 + + user_add(name, password) + return jsonify({"message": f"Użytkownik {name} zarejestrowany"}), 201 + + +@app.route('/api/login', methods=['POST']) +def api_login(): + """API endpoint do logowania (JSON)""" + data = request.get_json() + + if not data: + return jsonify({"error": "Brak danych JSON"}), 400 + + name = data.get('username') + password = data.get('password') + + if not name or not password: + return jsonify({"error": "Username i password są wymagane"}), 400 + + if not is_person(name): + return jsonify({"error": "Użytkownik nie istnieje"}), 404 + + if verify_password(name, password): + return jsonify({ + "message": "Zalogowano pomyślnie", + "user": name, + "status": "success" + }) + else: + return jsonify({"error": "Złe hasło"}), 401 + + +@app.route('/debug/users') +def debug_users(): + """Debug endpoint - pokazuje wszystkich użytkowników""" + if 'username' not in session: + return redirect(url_for('login')) + + users = get_all_users() + return jsonify(users) + +@app.route("/css/") +def css(): + return render_template("index_css.html") +if __name__ == '__main__': + app.run(port=2500) \ No newline at end of file diff --git a/file.json b/file.json new file mode 100644 index 0000000..3224b48 --- /dev/null +++ b/file.json @@ -0,0 +1,8 @@ +{ + "users": [ + { + "user": "neon", + "password": "1234" + } + ] +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..09e39f7 --- /dev/null +++ b/makefile @@ -0,0 +1,284 @@ +# Zmienne +PYTHON = venv/bin/python +PIP = venv/bin/pip +FLASK = venv/bin/flask +APP = app.py +PORT = 2500 +PROD_PORT = 8000 +DOMAIN = http.pathl.pl +PROJECT_DIR = /home/neon/PycharmProjects/http +VENV_DIR = $(PROJECT_DIR)/venv + +# Kolory do outputu +GREEN = \033[0;32m +RED = \033[0;31m +YELLOW = \033[1;33m +BLUE = \033[0;34m +NC = \033[0m # No Color + +.PHONY: help setup venv install run debug clean test api status kill reset release prod-start prod-stop prod-restart prod-status init-db backup + +help: + @echo "$(GREEN)Dostępne komendy:$(NC)" + @echo "" + @echo "$(BLUE)=== Rozwój (Development) ===$(NC)" + @echo " make setup - Przygotowanie środowiska (venv + zależności)" + @echo " make venv - Tworzenie środowiska wirtualnego" + @echo " make install - Instalacja zależności" + @echo " make debug - Uruchomienie serwera w trybie debug (port $(PORT))" + @echo " make run - Uruchomienie serwera (standardowo)" + @echo "" + @echo "$(BLUE)=== Produkcja (Production) ===$(NC)" + @echo " make release - Pełne wdrożenie produkcyjne (budowa + start)" + @echo " make prod-start - Uruchomienie serwera produkcyjnego (Gunicorn)" + @echo " make prod-stop - Zatrzymanie serwera produkcyjnego" + @echo " make prod-restart - Restart serwera produkcyjnego" + @echo " make prod-status - Status serwera produkcyjnego" + @echo "" + @echo "$(BLUE)=== Narzędzia ===$(NC)" + @echo " make clean - Usunięcie plików tymczasowych" + @echo " make test - Testowanie API" + @echo " make api - Pokazuje endpointy API" + @echo " make status - Sprawdza status serwera deweloperskiego" + @echo " make kill - Zabija proces Flask na porcie $(PORT)" + @echo " make reset - Resetuje bazę danych (usuwa file.json)" + @echo " make backup - Backup bazy danych" + @echo " make logs - Podgląd logów produkcyjnych" + +# ==================== DEVELOPMENT ==================== + +setup: venv install + @echo "$(GREEN)✓ Środowisko gotowe!$(NC)" + @echo "Uruchom: make debug" + +venv: + @echo "$(GREEN)Tworzenie środowiska wirtualnego...$(NC)" + @python3 -m venv venv || python -m venv venv + @echo "$(GREEN)✓ Środowisko utworzone$(NC)" + +install: + @echo "$(GREEN)Instalacja zależności...$(NC)" + @$(PIP) install --upgrade pip + @$(PIP) install flask + @$(PIP) install flask-cors + @$(PIP) install gunicorn + @$(PIP) install python-dotenv + @echo "$(GREEN)✓ Zależności zainstalowane$(NC)" + @# Tworzenie requirements.txt + @$(PIP) freeze > requirements.txt 2>/dev/null || true + +run: + @echo "$(GREEN)Uruchamianie serwera na porcie $(PORT)...$(NC)" + @$(PYTHON) $(APP) + +debug: + @echo "$(GREEN)Uruchamianie serwera w trybie DEBUG na porcie $(PORT)...$(NC)" + @export FLASK_ENV=development FLASK_DEBUG=1 && $(PYTHON) $(APP) + +clean: + @echo "$(GREEN)Czyszczenie plików tymczasowych...$(NC)" + @find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true + @find . -type f -name "*.pyc" -delete 2>/dev/null || true + @find . -type f -name "*.pyo" -delete 2>/dev/null || true + @rm -rf .pytest_cache 2>/dev/null || true + @echo "$(GREEN)✓ Pliki tymczasowe usunięte$(NC)" + +# ==================== PRODUCTION ==================== + +release: clean install prod-stop prod-start prod-status + @echo "$(GREEN)========================================$(NC)" + @echo "$(GREEN)✓ Wdrożenie produkcyjne zakończone!$(NC)" + @echo "$(GREEN)========================================$(NC)" + @echo "Aplikacja dostępna pod adresem: http://$(DOMAIN)" + @echo "Port: $(PROD_PORT)" + @echo "" + @echo "Aby sprawdzić status: make prod-status" + @echo "Aby zatrzymać: make prod-stop" + @echo "Aby zobaczyć logi: make logs" + +prod-start: + @echo "$(GREEN)Uruchamianie serwera produkcyjnego...$(NC)" + @echo "Domena: http://$(DOMAIN)" + @echo "Port: $(PROD_PORT)" + @# Zabij stary proces jeśli istnieje + @-lsof -ti :$(PROD_PORT) | xargs kill -9 2>/dev/null || true + @# Uruchom Gunicorn w tle + @cd $(PROJECT_DIR) && nohup $(VENV_DIR)/bin/gunicorn -w 4 -b 0.0.0.0:$(PROD_PORT) app:app > logs/production.log 2>&1 & + @sleep 2 + @echo "$(GREEN)✓ Serwer produkcyjny uruchomiony!$(NC)" + @echo "PID: $$(lsof -ti :$(PROD_PORT) 2>/dev/null || echo 'Nie można odczytać')" + @echo "Logi: $(PROJECT_DIR)/logs/production.log" + +prod-stop: + @echo "$(RED)Zatrzymywanie serwera produkcyjnego...$(NC)" + @-lsof -ti :$(PROD_PORT) | xargs kill -9 2>/dev/null && echo "$(GREEN)✓ Serwer zatrzymany$(NC)" || echo "Serwer nie był uruchomiony" + @-pkill -f "gunicorn.*app:app" 2>/dev/null || true + +prod-restart: prod-stop prod-start + @echo "$(GREEN)✓ Serwer produkcyjny zrestartowany$(NC)" + +prod-status: + @echo "$(BLUE)Status serwera produkcyjnego:$(NC)" + @if lsof -i :$(PROD_PORT) > /dev/null 2>&1; then \ + echo "$(GREEN)✓ Serwer DZIAŁA na porcie $(PROD_PORT)$(NC)"; \ + echo "Domena: http://$(DOMAIN)"; \ + echo "PID: $$(lsof -ti :$(PROD_PORT))"; \ + echo ""; \ + echo "Test połączenia:"; \ + curl -s -o /dev/null -w "Status HTTP: %{http_code}\n" http://localhost:$(PROD_PORT)/; \ + else \ + echo "$(RED)✗ Serwer NIE działa na porcie $(PROD_PORT)$(NC)"; \ + fi + +# ==================== UTILS ==================== + +test: + @echo "$(GREEN)Testowanie API (dev:$(PORT), prod:$(PROD_PORT))...$(NC)" + @echo "$(YELLOW)1. Test root endpoint (dev):$(NC)" + @curl -s http://localhost:$(PORT)/ 2>/dev/null | head -c 200 || echo "Serwer dev nie uruchomiony" + @echo "\n$(YELLOW)2. Test API check user (prod):$(NC)" + @curl -s http://localhost:$(PROD_PORT)/api/check/admin 2>/dev/null || echo "Serwer prod nie uruchomiony" + @echo "\n$(YELLOW)3. Test API get users (prod):$(NC)" + @curl -s http://localhost:$(PROD_PORT)/api/users 2>/dev/null || echo "Serwer prod nie uruchomiony" + @echo "" + +api: + @echo "$(GREEN)Dostępne endpointy API:$(NC)" + @echo "" + @echo "$(BLUE)Deweloperskie (http://localhost:$(PORT)):$(NC)" + @echo " GET / - Strona główna" + @echo " GET /register - Formularz rejestracji" + @echo " POST /register - Rejestracja użytkownika" + @echo " GET /login - Formularz logowania" + @echo " POST /login - Logowanie" + @echo " GET /dashboard - Panel użytkownika" + @echo " GET /logout - Wylogowanie" + @echo "" + @echo "$(BLUE)Produkcyjne (http://$(DOMAIN)):$(NC)" + @echo " GET /api/users - Lista wszystkich użytkowników" + @echo " GET /api/passwd/ - Pobierz hasło użytkownika" + @echo " GET /api/check/ - Sprawdź czy użytkownik istnieje" + @echo " POST /api/register - Rejestracja przez API (JSON)" + @echo " POST /api/login - Logowanie przez API (JSON)" + @echo "" + @echo "$(GREEN)Przykłady użycia API (produkcja):$(NC)" + @echo " curl -X POST http://$(DOMAIN)/api/register \\" + @echo " -H \"Content-Type: application/json\" \\" + @echo " -d '{\"username\":\"test\",\"password\":\"123\"}'" + @echo "" + @echo " curl http://$(DOMAIN)/api/check/test" + @echo " curl http://$(DOMAIN)/api/users" + +status: + @echo "$(GREEN)Sprawdzanie statusu serwerów:$(NC)" + @echo "" + @echo "$(BLUE)Development (port $(PORT)):$(NC)" + @if lsof -i :$(PORT) > /dev/null 2>&1; then \ + echo " $(GREEN)✓ Działa$(NC) - PID: $$(lsof -ti :$(PORT))"; \ + else \ + echo " $(RED)✗ Nie działa$(NC)"; \ + fi + @echo "" + @echo "$(BLUE)Production (port $(PROD_PORT)):$(NC)" + @if lsof -i :$(PROD_PORT) > /dev/null 2>&1; then \ + echo " $(GREEN)✓ Działa$(NC) - PID: $$(lsof -ti :$(PROD_PORT))"; \ + echo " URL: http://$(DOMAIN)"; \ + else \ + echo " $(RED)✗ Nie działa$(NC)"; \ + fi + +kill: + @echo "$(RED)Zabijanie procesu deweloperskiego na porcie $(PORT)...$(NC)" + @lsof -ti :$(PORT) | xargs kill -9 2>/dev/null || echo "Brak procesu na porcie $(PORT)" + @echo "$(GREEN)✓ Proces deweloperski zabity$(NC)" + +reset: + @echo "$(RED)Resetowanie bazy danych...$(NC)" + @rm -f file.json + @echo "{}" > file.json + @echo "$(GREEN)✓ Baza danych zresetowana (file.json)$(NC)" + +backup: + @echo "$(GREEN)Tworzenie backupu bazy danych...$(NC)" + @if [ -f file.json ]; then \ + cp file.json file.json.backup.$$(date +%Y%m%d_%H%M%S); \ + echo "$(GREEN)✓ Backup utworzony$(NC)"; \ + else \ + echo "$(YELLOW)Brak bazy danych do backupu$(NC)"; \ + fi + +logs: + @echo "$(GREEN)Logi produkcyjne (Ctrl+C aby zakończyć):$(NC)" + @mkdir -p logs + @tail -f logs/production.log 2>/dev/null || echo "Brak logów - uruchom najpierw make prod-start" + +init-db: + @echo "$(GREEN)Inicjalizacja bazy danych...$(NC)" + @if [ ! -f file.json ]; then \ + echo '{"users": []}' > file.json; \ + echo "$(GREEN)✓ Utworzono nową bazę danych$(NC)"; \ + else \ + echo "$(YELLOW)Baza danych już istnieje$(NC)"; \ + fi + +# ==================== PRODUCTION SETUP ==================== + +prod-setup: clean install init-db + @echo "$(GREEN)✓ Środowisko produkcyjne gotowe$(NC)" + @mkdir -p logs + @echo "Uruchom: make release" + +# ==================== DLA SYSTEMD (autostart) ==================== + +install-service: + @echo "$(GREEN)Instalacja usługi systemd...$(NC)" + @sudo bash -c 'cat > /etc/systemd/system/http-api.service << EOF +[Unit] +Description=HTTP API Flask App +After=network.target + +[Service] +User=$(shell whoami) +WorkingDirectory=$(PROJECT_DIR) +ExecStart=$(VENV_DIR)/bin/gunicorn -w 4 -b 0.0.0.0:$(PROD_PORT) app:app +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +EOF' + @sudo systemctl daemon-reload + @echo "$(GREEN)✓ Usługa zainstalowana$(NC)" + @echo "Uruchom: sudo systemctl start http-api" + @echo "Włącz autostart: sudo systemctl enable http-api" + +remove-service: + @echo "$(RED)Usuwanie usługi systemd...$(NC)" + @sudo systemctl stop http-api 2>/dev/null || true + @sudo systemctl disable http-api 2>/dev/null || true + @sudo rm -f /etc/systemd/system/http-api.service + @sudo systemctl daemon-reload + @echo "$(GREEN)✓ Usługa usunięta$(NC)" + +# ==================== DLA NGINX (proxy) ==================== + +setup-nginx: + @echo "$(GREEN)Konfiguracja Nginx jako reverse proxy...$(NC)" + @sudo bash -c 'cat > /etc/nginx/sites-available/http-api << EOF +server { + listen 80; + server_name $(DOMAIN); + + location / { + proxy_pass http://127.0.0.1:$(PROD_PORT); + proxy_set_header Host $$host; + proxy_set_header X-Real-IP $$remote_addr; + proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $$scheme; + } +} +EOF' + @sudo ln -sf /etc/nginx/sites-available/http-api /etc/nginx/sites-enabled/ + @sudo nginx -t && sudo systemctl reload nginx + @echo "$(GREEN)✓ Nginx skonfigurowany$(NC)" + @echo "Domena: http://$(DOMAIN)" \ No newline at end of file diff --git a/main.py b/static/css/style.css similarity index 100% rename from main.py rename to static/css/style.css diff --git a/templates/dashboard.html b/templates/dashboard.html new file mode 100644 index 0000000..4a93725 --- /dev/null +++ b/templates/dashboard.html @@ -0,0 +1,29 @@ + + + + + + Panel użytkownika + + + +
+

Witaj, {{ user.user }}!

+
+

Zalogowany jako: {{ user.user }}

+

Twoje hasło: {{ user.password }}

+
+ + Wyloguj się + +
+

Informacje API:

+

GET /api/users - lista wszystkich użytkowników

+

GET /api/passwd/<nazwa> - pobierz hasło użytkownika

+

GET /api/check/<nazwa> - sprawdź czy użytkownik istnieje

+

Zobacz stronę z CSS:

+ Kliknij tutaj, aby przejść +
+
+ + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..ffb05de --- /dev/null +++ b/templates/index.html @@ -0,0 +1,19 @@ + + + + + + Strona Główna + + + +
+

Witaj na naszej stronie!

+

System rejestracji i logowania użytkowników

+ +
+ + \ No newline at end of file diff --git a/templates/index_css.html b/templates/index_css.html new file mode 100644 index 0000000..13bb013 --- /dev/null +++ b/templates/index_css.html @@ -0,0 +1,45 @@ + + + + + Prosta strona z CSS + + + +

Witaj na mojej prostej stronie!

+

To jest przykładowa strona HTML z prostym CSS.

+ Powrót do strony głównej + + \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..90a345c --- /dev/null +++ b/templates/login.html @@ -0,0 +1,22 @@ + + + + + + Logowanie + + + +
+

Logowanie

+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/templates/register.html b/templates/register.html new file mode 100644 index 0000000..d7def55 --- /dev/null +++ b/templates/register.html @@ -0,0 +1,23 @@ + + + + + + Rejestracja + + + +
+

Rejestracja

+
+ + + + +
+ +
+ + \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..e69de29 diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..2b02df5 --- /dev/null +++ b/utils.py @@ -0,0 +1,118 @@ +import json +import os + + +def user_add(new_user, new_password): + """Dodaje nowego użytkownika lub aktualizuje hasło""" + file_path = "file.json" + + # Wczytanie pliku JSON + if os.path.exists(file_path): + with open(file_path, "r") as f: + try: + data = json.load(f) + except json.JSONDecodeError: + data = {"users": []} + else: + data = {"users": []} + + # Sprawdź czy użytkownik już istnieje + for entry in data["users"]: + if entry.get("user") == new_user: + # Aktualizuj hasło + entry["password"] = new_password + with open(file_path, "w") as f: + json.dump(data, f, indent=4) + return False # Zaktualizowano + + # Dodaj nowego użytkownika + new_entry = {"user": new_user, "password": new_password} + data["users"].append(new_entry) + + # Zapis do pliku JSON + with open(file_path, "w") as f: + json.dump(data, f, indent=4) + return True # Dodano nowego + + +def is_person(user_to_find): + """Sprawdza czy użytkownik istnieje - zwraca 1 lub 0""" + file_path = "file.json" + + try: + with open(file_path, "r") as f: + data = json.load(f) + except (FileNotFoundError, json.JSONDecodeError): + return 0 + + for entry in data.get("users", []): + if entry.get("user") == user_to_find: + return 1 + return 0 + + +def verify_password(user_to_check, password_to_check): + """Sprawdza hasło bez usuwania użytkownika""" + file_path = "file.json" + + try: + with open(file_path, "r") as f: + data = json.load(f) + except (FileNotFoundError, json.JSONDecodeError): + return False + + for entry in data.get("users", []): + if entry.get("user") == user_to_check: + return entry.get("password") == password_to_check + + return False + + +def get_user_data(user_to_find): + """Pobiera dane użytkownika bez usuwania""" + file_path = "file.json" + + try: + with open(file_path, "r") as f: + data = json.load(f) + except (FileNotFoundError, json.JSONDecodeError): + return None + + for entry in data.get("users", []): + if entry.get("user") == user_to_find: + return {"user": entry["user"], "password": entry["password"]} + + return None + + +def get_all_users(): + """Zwraca listę wszystkich użytkowników""" + file_path = "file.json" + + try: + with open(file_path, "r") as f: + data = json.load(f) + except (FileNotFoundError, json.JSONDecodeError): + return [] + + return data.get("users", []) + + +def delete_user(user_to_delete): + """Usuwa użytkownika z bazy""" + file_path = "file.json" + + try: + with open(file_path, "r") as f: + data = json.load(f) + except (FileNotFoundError, json.JSONDecodeError): + return False + + for i, entry in enumerate(data.get("users", [])): + if entry.get("user") == user_to_delete: + data["users"].pop(i) + with open(file_path, "w") as f: + json.dump(data, f, indent=4) + return True + + return False \ No newline at end of file