From e3724a48426295eafb5d8071f9ede52ab5d1d949 Mon Sep 17 00:00:00 2001 From: Josh-Dev-Quest Date: Sat, 28 Mar 2026 13:36:17 +0100 Subject: [PATCH] Moved authentification code into js/auth.js --- backend/app.py | 292 ++++++++++++++++------------- backend/data/users/1/journeys.json | 43 ++++- backend/data/users/1/posts.json | 11 +- blog-list.html | 57 +----- blog-post-edit.html | 58 +----- js/auth.js | 67 +++++++ login.html | 105 +++++------ map-page.html | 61 +----- 8 files changed, 330 insertions(+), 364 deletions(-) create mode 100644 js/auth.js diff --git a/backend/app.py b/backend/app.py index 4823853..f3a62e4 100644 --- a/backend/app.py +++ b/backend/app.py @@ -6,109 +6,120 @@ import os from datetime import datetime app = Flask(__name__) -app.secret_key = 'your-secret-key-here-change-in-production' # needed for sessions +app.secret_key = "your-secret-key-here-change-in-production" # needed for sessions CORS(app, supports_credentials=True) # allow cookies # Directories -DATA_DIR = 'data' -USERS_FILE = os.path.join(DATA_DIR, 'users.json') +DATA_DIR = "data" +USERS_FILE = os.path.join(DATA_DIR, "users.json") os.makedirs(DATA_DIR, exist_ok=True) + # ==================== User helpers ==================== def load_users(): try: if os.path.exists(USERS_FILE): - with open(USERS_FILE, 'r') as f: + with open(USERS_FILE, "r") as f: return json.load(f) except Exception as e: print(f"Error loading users: {e}") return [] + def save_users(users): try: - with open(USERS_FILE, 'w') as f: + with open(USERS_FILE, "w") as f: json.dump(users, f, indent=2) except Exception as e: print(f"Error saving users: {e}") + def get_next_user_id(users): if not users: return 1 - return max(u['id'] for u in users) + 1 + return max(u["id"] for u in users) + 1 + def get_user_by_username(username): users = load_users() - return next((u for u in users if u['username'] == username), None) + return next((u for u in users if u["username"] == username), None) + def get_user_by_id(user_id): users = load_users() - return next((u for u in users if u['id'] == user_id), None) + return next((u for u in users if u["id"] == user_id), None) + # ==================== Per‑user data helpers ==================== def get_user_data_dir(user_id): - user_dir = os.path.join(DATA_DIR, 'users', str(user_id)) + user_dir = os.path.join(DATA_DIR, "users", str(user_id)) os.makedirs(user_dir, exist_ok=True) return user_dir + def load_user_journeys(user_id): - file_path = os.path.join(get_user_data_dir(user_id), 'journeys.json') + file_path = os.path.join(get_user_data_dir(user_id), "journeys.json") try: if os.path.exists(file_path): - with open(file_path, 'r') as f: + with open(file_path, "r") as f: return json.load(f) except Exception as e: print(f"Error loading journeys for user {user_id}: {e}") return [] + def save_user_journeys(user_id, journeys): - file_path = os.path.join(get_user_data_dir(user_id), 'journeys.json') + file_path = os.path.join(get_user_data_dir(user_id), "journeys.json") try: - with open(file_path, 'w') as f: + with open(file_path, "w") as f: json.dump(journeys, f, indent=2) except Exception as e: print(f"Error saving journeys for user {user_id}: {e}") + def load_user_posts(user_id): - file_path = os.path.join(get_user_data_dir(user_id), 'posts.json') + file_path = os.path.join(get_user_data_dir(user_id), "posts.json") try: if os.path.exists(file_path): - with open(file_path, 'r') as f: + with open(file_path, "r") as f: return json.load(f) except Exception as e: print(f"Error loading posts for user {user_id}: {e}") return [] + def save_user_posts(user_id, posts): - file_path = os.path.join(get_user_data_dir(user_id), 'posts.json') + file_path = os.path.join(get_user_data_dir(user_id), "posts.json") try: - with open(file_path, 'w') as f: + with open(file_path, "w") as f: json.dump(posts, f, indent=2) except Exception as e: print(f"Error saving posts for user {user_id}: {e}") + # ==================== Authentication endpoints ==================== -@app.route('/api/register', methods=['POST']) +@app.route("/api/register", methods=["POST"]) def register(): data = request.get_json() - username = data.get('username') - password = data.get('password') + username = data.get("username") + password = data.get("password") if not username or not password: - return jsonify({'error': 'Username and password required'}), 400 + return jsonify({"error": "Username and password required"}), 400 # Check if username already exists if get_user_by_username(username): - return jsonify({'error': 'Username already taken'}), 409 + return jsonify({"error": "Username already taken"}), 409 users = load_users() new_id = get_next_user_id(users) hashed = generate_password_hash(password) new_user = { - 'id': new_id, - 'username': username, - 'password_hash': hashed, - 'created_at': datetime.now().isoformat() + "id": new_id, + "username": username, + "password_hash": hashed, + "created_at": datetime.now().isoformat(), } users.append(new_user) save_users(users) @@ -118,59 +129,58 @@ def register(): save_user_posts(new_id, []) # Log the user in automatically - session['user_id'] = new_id + session["user_id"] = new_id - return jsonify({ - 'id': new_id, - 'username': username, - 'message': 'Registration successful' - }), 201 + return jsonify( + {"id": new_id, "username": username, "message": "Registration successful"} + ), 201 -@app.route('/api/login', methods=['POST']) + +@app.route("/api/login", methods=["POST"]) def login(): data = request.get_json() - username = data.get('username') - password = data.get('password') + username = data.get("username") + password = data.get("password") user = get_user_by_username(username) - if not user or not check_password_hash(user['password_hash'], password): - return jsonify({'error': 'Invalid username or password'}), 401 + if not user or not check_password_hash(user["password_hash"], password): + return jsonify({"error": "Invalid username or password"}), 401 - session['user_id'] = user['id'] - return jsonify({ - 'id': user['id'], - 'username': user['username'], - 'message': 'Login successful' - }) + session["user_id"] = user["id"] + return jsonify( + {"id": user["id"], "username": user["username"], "message": "Login successful"} + ) -@app.route('/api/logout', methods=['POST']) + +@app.route("/api/logout", methods=["POST"]) def logout(): - session.pop('user_id', None) - return jsonify({'message': 'Logged out'}) + session.pop("user_id", None) + return jsonify({"message": "Logged out"}) -@app.route('/api/me', methods=['GET']) + +@app.route("/api/me", methods=["GET"]) def me(): - user_id = session.get('user_id') + user_id = session.get("user_id") if not user_id: - return jsonify({'error': 'Not logged in'}), 401 + return jsonify({"error": "Not logged in"}), 401 user = get_user_by_id(user_id) if not user: # Should not happen, but clean session - session.pop('user_id', None) - return jsonify({'error': 'User not found'}), 401 - return jsonify({ - 'id': user['id'], - 'username': user['username'] - }) + session.pop("user_id", None) + return jsonify({"error": "User not found"}), 401 + return jsonify({"id": user["id"], "username": user["username"]}) + # ==================== Journey endpoints (protected, user‑specific) ==================== def require_login(): - if 'user_id' not in session: + if "user_id" not in session: return False return True + def get_current_user_id(): - return session.get('user_id') + return session.get("user_id") + def get_journeys_for_current_user(): user_id = get_current_user_id() @@ -178,91 +188,98 @@ def get_journeys_for_current_user(): return None return load_user_journeys(user_id) -@app.route('/api/journeys', methods=['GET']) + +@app.route("/api/journeys", methods=["GET"]) def get_journeys(): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 journeys = get_journeys_for_current_user() return jsonify(journeys) + def get_next_journey_id(journeys): if not journeys: return 1 - return max(j['id'] for j in journeys) + 1 + return max(j["id"] for j in journeys) + 1 -@app.route('/api/journeys', methods=['POST']) + +@app.route("/api/journeys", methods=["POST"]) def create_journey(): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 data = request.get_json() if not data: - return jsonify({'error': 'No data provided'}), 400 + return jsonify({"error": "No data provided"}), 400 - title = data.get('title') + title = data.get("title") if not title: - return jsonify({'error': 'Journey title is required'}), 400 + return jsonify({"error": "Journey title is required"}), 400 user_id = get_current_user_id() journeys = get_journeys_for_current_user() new_id = get_next_journey_id(journeys) new_journey = { - 'id': new_id, - 'title': title, - 'description': data.get('description', ''), - 'markers': data.get('markers', []), - 'created_at': datetime.now().isoformat() + "id": new_id, + "title": title, + "description": data.get("description", ""), + "markers": data.get("markers", []), + "created_at": datetime.now().isoformat(), } journeys.append(new_journey) save_user_journeys(user_id, journeys) return jsonify(new_journey), 201 -@app.route('/api/journeys/', methods=['GET']) + +@app.route("/api/journeys/", methods=["GET"]) def get_journey(journey_id): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 journeys = get_journeys_for_current_user() - journey = next((j for j in journeys if j['id'] == journey_id), None) + journey = next((j for j in journeys if j["id"] == journey_id), None) if journey is None: - return jsonify({'error': 'Journey not found'}), 404 + return jsonify({"error": "Journey not found"}), 404 return jsonify(journey) -@app.route('/api/journeys/', methods=['PUT']) + +@app.route("/api/journeys/", methods=["PUT"]) def update_journey(journey_id): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 journeys = get_journeys_for_current_user() - journey = next((j for j in journeys if j['id'] == journey_id), None) + journey = next((j for j in journeys if j["id"] == journey_id), None) if journey is None: - return jsonify({'error': 'Journey not found'}), 404 + return jsonify({"error": "Journey not found"}), 404 data = request.get_json() if not data: - return jsonify({'error': 'No data provided'}), 400 + return jsonify({"error": "No data provided"}), 400 - if 'title' in data: - journey['title'] = data['title'] - if 'description' in data: - journey['description'] = data['description'] - if 'markers' in data: - journey['markers'] = data['markers'] + if "title" in data: + journey["title"] = data["title"] + if "description" in data: + journey["description"] = data["description"] + if "markers" in data: + journey["markers"] = data["markers"] save_user_journeys(get_current_user_id(), journeys) return jsonify(journey) -@app.route('/api/journeys/', methods=['DELETE']) + +@app.route("/api/journeys/", methods=["DELETE"]) def delete_journey(journey_id): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 journeys = get_journeys_for_current_user() - journey = next((j for j in journeys if j['id'] == journey_id), None) + journey = next((j for j in journeys if j["id"] == journey_id), None) if journey is None: - return jsonify({'error': 'Journey not found'}), 404 + return jsonify({"error": "Journey not found"}), 404 - journeys = [j for j in journeys if j['id'] != journey_id] + journeys = [j for j in journeys if j["id"] != journey_id] save_user_journeys(get_current_user_id(), journeys) - return jsonify({'message': 'Journey deleted successfully', 'journey': journey}) + return jsonify({"message": "Journey deleted successfully", "journey": journey}) + # ==================== Blog Post endpoints (protected, user‑specific) ==================== def get_posts_for_current_user(): @@ -271,97 +288,105 @@ def get_posts_for_current_user(): return None return load_user_posts(user_id) + def get_next_post_id(posts): if not posts: return 1 - return max(p['id'] for p in posts) + 1 + return max(p["id"] for p in posts) + 1 -@app.route('/api/blog-posts', methods=['GET']) + +@app.route("/api/blog-posts", methods=["GET"]) def get_blog_posts(): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 posts = get_posts_for_current_user() return jsonify(posts) -@app.route('/api/blog-posts/', methods=['GET']) + +@app.route("/api/blog-posts/", methods=["GET"]) def get_blog_post(post_id): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 posts = get_posts_for_current_user() - post = next((p for p in posts if p['id'] == post_id), None) + post = next((p for p in posts if p["id"] == post_id), None) if not post: - return jsonify({'error': 'Post not found'}), 404 + return jsonify({"error": "Post not found"}), 404 return jsonify(post) -@app.route('/api/blog-posts', methods=['POST']) + +@app.route("/api/blog-posts", methods=["POST"]) def create_blog_post(): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 data = request.get_json() - title = data.get('title') + title = data.get("title") if not title: - return jsonify({'error': 'Title required'}), 400 + return jsonify({"error": "Title required"}), 400 user_id = get_current_user_id() posts = get_posts_for_current_user() new_id = get_next_post_id(posts) new_post = { - 'id': new_id, - 'title': title, - 'content': data.get('content', ''), - 'journeyId': data.get('journeyId'), - 'image': data.get('image'), - 'created_at': datetime.now().isoformat() + "id": new_id, + "title": title, + "content": data.get("content", ""), + "journeyId": data.get("journeyId"), + "image": data.get("image"), + "created_at": datetime.now().isoformat(), } posts.append(new_post) save_user_posts(user_id, posts) return jsonify(new_post), 201 -@app.route('/api/blog-posts/', methods=['PUT']) + +@app.route("/api/blog-posts/", methods=["PUT"]) def update_blog_post(post_id): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 posts = get_posts_for_current_user() - post = next((p for p in posts if p['id'] == post_id), None) + post = next((p for p in posts if p["id"] == post_id), None) if not post: - return jsonify({'error': 'Post not found'}), 404 + return jsonify({"error": "Post not found"}), 404 data = request.get_json() - if 'title' in data: - post['title'] = data['title'] - if 'content' in data: - post['content'] = data['content'] - if 'journeyId' in data: - post['journeyId'] = data['journeyId'] - if 'image' in data: - post['image'] = data['image'] + if "title" in data: + post["title"] = data["title"] + if "content" in data: + post["content"] = data["content"] + if "journeyId" in data: + post["journeyId"] = data["journeyId"] + if "image" in data: + post["image"] = data["image"] save_user_posts(get_current_user_id(), posts) return jsonify(post) -@app.route('/api/blog-posts/', methods=['DELETE']) + +@app.route("/api/blog-posts/", methods=["DELETE"]) def delete_blog_post(post_id): if not require_login(): - return jsonify({'error': 'Authentication required'}), 401 + return jsonify({"error": "Authentication required"}), 401 posts = get_posts_for_current_user() - post = next((p for p in posts if p['id'] == post_id), None) + post = next((p for p in posts if p["id"] == post_id), None) if not post: - return jsonify({'error': 'Post not found'}), 404 + return jsonify({"error": "Post not found"}), 404 - posts = [p for p in posts if p['id'] != post_id] + posts = [p for p in posts if p["id"] != post_id] save_user_posts(get_current_user_id(), posts) - return jsonify({'message': 'Post deleted'}) + return jsonify({"message": "Post deleted"}) + # ==================== Health and root ==================== -@app.route('/api/journeys/health', methods=['GET']) +@app.route("/api/journeys/health", methods=["GET"]) def health_check(): - return jsonify({'status': 'healthy', 'timestamp': datetime.now().isoformat()}) + return jsonify({"status": "healthy", "timestamp": datetime.now().isoformat()}) -@app.route('/') + +@app.route("/") def index(): - return ''' + return """ Journey Mapper API @@ -371,7 +396,8 @@ def index():

Authentication required: register, login, then use session cookies.

- ''' + """ -if __name__ == '__main__': - app.run(debug=True, port=5000) \ No newline at end of file + +if __name__ == "__main__": + app.run(debug=True, port=5000) diff --git a/backend/data/users/1/journeys.json b/backend/data/users/1/journeys.json index 0637a08..e67038d 100644 --- a/backend/data/users/1/journeys.json +++ b/backend/data/users/1/journeys.json @@ -1 +1,42 @@ -[] \ No newline at end of file +[ + { + "id": 1, + "title": "test", + "description": "11", + "markers": [ + { + "lat": 48.356249029540734, + "lng": 4.866943359375, + "title": "New Marker", + "date": "", + "description": "", + "videoUrl": "" + }, + { + "lat": 46.961510504873104, + "lng": 9.371337890625002, + "title": "New Marker", + "date": "", + "description": "", + "videoUrl": "" + }, + { + "lat": 45.51404592560427, + "lng": 11.656494140625002, + "title": "New Marker", + "date": "", + "description": "", + "videoUrl": "" + }, + { + "lat": 43.52465500687188, + "lng": 11.162109375, + "title": "New Marker", + "date": "", + "description": "", + "videoUrl": "" + } + ], + "created_at": "2026-03-27T21:49:26.885353" + } +] \ No newline at end of file diff --git a/backend/data/users/1/posts.json b/backend/data/users/1/posts.json index 0637a08..1763773 100644 --- a/backend/data/users/1/posts.json +++ b/backend/data/users/1/posts.json @@ -1 +1,10 @@ -[] \ No newline at end of file +[ + { + "id": 1, + "title": "test", + "content": "ksafladjsfk", + "journeyId": "1", + "image": null, + "created_at": "2026-03-27T21:23:39.755057" + } +] \ No newline at end of file diff --git a/blog-list.html b/blog-list.html index 556e42b..5878475 100644 --- a/blog-list.html +++ b/blog-list.html @@ -220,62 +220,9 @@
- + + - \ No newline at end of file + diff --git a/map-page.html b/map-page.html index cc1532c..be193bd 100644 --- a/map-page.html +++ b/map-page.html @@ -876,65 +876,10 @@

+