From 51f154ab731e9039f5ef1a00d5176bab240bca32 Mon Sep 17 00:00:00 2001 From: Blake Ridgway Date: Sat, 15 Feb 2025 18:58:48 -0600 Subject: [PATCH] (feat): Added PostgreSQL connection string encoding. --- models/__init__.py | 21 +++++++++++++++++++-- models/user.py | 17 ++++++++++++++++- routes/auth.py | 4 +--- server.py | 10 ++++------ services/user.py | 25 +++++-------------------- 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/models/__init__.py b/models/__init__.py index 96c5d7b..a53c270 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,5 +1,22 @@ +import os from flask_sqlalchemy import SQLAlchemy -from flask_bcrypt import Bcrypt +from dotenv import load_dotenv +from urllib.parse import quote_plus + +load_dotenv() + +PG_USER = quote_plus(os.getenv('PG_USER')) +PG_PASSWORD = quote_plus(os.getenv('PG_PASSWORD')) +PG_HOST = os.getenv('PG_HOST') +PG_PORT = os.getenv('PG_PORT') +PG_DATABASE = os.getenv('PG_DATABASE') + +DATABASE_URI = f"postgresql+psycopg2://{PG_USER}:{PG_PASSWORD}@{PG_HOST}:{PG_PORT}/{PG_DATABASE}" db = SQLAlchemy() -bcrypt = Bcrypt() \ No newline at end of file + +def init_db(app): + """Initialize the SQLAlchemy app with the configuration.""" + app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE_URI + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + db.init_app(app) diff --git a/models/user.py b/models/user.py index 0092d1a..0cdc1e2 100644 --- a/models/user.py +++ b/models/user.py @@ -1,8 +1,23 @@ from models import db +from werkzeug.security import generate_password_hash, check_password_hash class User(db.Model): __tablename__ = 'users' - + id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password = db.Column(db.String(128), nullable=False) + + def __init__(self, username, password, hash_password=True): + self.username = username + # Optionally hash the password automatically. + if hash_password: + self.password = generate_password_hash(password, method="pbkdf2:sha256") + else: + self.password = password + + def check_password(self, password): + return check_password_hash(self.password, password) + + def __repr__(self): + return f"" \ No newline at end of file diff --git a/routes/auth.py b/routes/auth.py index 770cc96..f73a97b 100644 --- a/routes/auth.py +++ b/routes/auth.py @@ -15,8 +15,6 @@ def signup(): return jsonify({"message": "User created successfully", "username": new_user.username}), 201 except ValueError as e: return jsonify({"message": str(e)}), 400 - - @auth_bp.route('/login', methods=['POST']) def login(): @@ -28,4 +26,4 @@ def login(): user = user_service.verify_user(username, password) return jsonify({"message": "Login successful", "user_id": user.id}), 200 except ValueError as e: - return jsonify({"error": str(e)}), 401 \ No newline at end of file + return jsonify({"error": str(e)}), 401 diff --git a/server.py b/server.py index cd38ee1..1a55e21 100644 --- a/server.py +++ b/server.py @@ -1,6 +1,6 @@ import os from flask import Flask -from models import db, bcrypt +from models import db, init_db from routes.auth import auth_bp from dotenv import load_dotenv from flask_cors import CORS @@ -8,14 +8,12 @@ from flask_cors import CORS load_dotenv() app = Flask(__name__) +CORS(app) -CORS(app) - -app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE') +app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE') # Or use DATABASE_URI from models app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -db.init_app(app) -bcrypt.init_app(app) +init_db(app) app.register_blueprint(auth_bp) diff --git a/services/user.py b/services/user.py index 600cb78..60754df 100644 --- a/services/user.py +++ b/services/user.py @@ -2,33 +2,18 @@ from werkzeug.security import generate_password_hash, check_password_hash from models.user import User, db class UserService: - def __init__(self): - self.db = db - def create_user(self, username, password): - # Check if the user exists existing_user = User.query.filter_by(username=username).first() if existing_user: raise ValueError("User already exists") - # Hash the password before storing - hash_password = generate_password_hash(password) - - # Create a new user - new_user = User(username=username, password=hash_password) - self.db.session.add(new_user) - self.db.session.commit() - + new_user = User(username=username, password=password) + db.session.add(new_user) + db.session.commit() return new_user def verify_user(self, username, password): - # Fetch the user by username user = User.query.filter_by(username=username).first() - if not user: + if not user or not user.check_password(password): raise ValueError("Invalid username or password") - - # Verify the hashed password - if not check_password_hash(user.password, password): - raise ValueError("Invalid username or password") - - return user \ No newline at end of file + return user