Compare commits
4 Commits
257eb80de7
...
dc919681fd
| Author | SHA1 | Date | |
|---|---|---|---|
| dc919681fd | |||
| 0589b2c8a5 | |||
| 96a5bcc9e8 | |||
| 66f1b26cc8 |
36
db/database.py
Normal file
36
db/database.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import os
|
||||||
|
import psycopg2
|
||||||
|
|
||||||
|
|
||||||
|
class PostgresConnector:
|
||||||
|
"""
|
||||||
|
Simple PostgreSQL connector (single connection).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.connection = psycopg2.connect(
|
||||||
|
host=os.getenv("POSTGRES_HOST", "localhost"),
|
||||||
|
port=os.getenv("POSTGRES_PORT", 5432),
|
||||||
|
user=os.getenv("POSTGRES_USER", "postgres"),
|
||||||
|
password=os.getenv("POSTGRES_PASSWORD", "postgres"),
|
||||||
|
database=os.getenv("POSTGRES_DB", "postgres"),
|
||||||
|
)
|
||||||
|
self.connection.autocommit = False
|
||||||
|
|
||||||
|
def execute(self, query, params=None, fetch=False):
|
||||||
|
with self.connection.cursor() as cursor:
|
||||||
|
cursor.execute(query, params)
|
||||||
|
|
||||||
|
if fetch:
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
self.connection.commit()
|
||||||
|
|
||||||
|
def executemany(self, query, param_list):
|
||||||
|
with self.connection.cursor() as cursor:
|
||||||
|
cursor.executemany(query, param_list)
|
||||||
|
self.connection.commit()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self.connection:
|
||||||
|
self.connection.close()
|
||||||
14
docker-compose.yml
Normal file
14
docker-compose.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16
|
||||||
|
container_name: postgres_db
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
beautifulsoup4==4.14.3
|
beautifulsoup4==4.14.3
|
||||||
Flask==3.1.2
|
Flask==3.1.3
|
||||||
flask_cors==6.0.2
|
flask_cors==6.0.2
|
||||||
google_api_python_client==2.188.0
|
google_api_python_client==2.188.0
|
||||||
keybert==0.9.0
|
|
||||||
nltk==3.9.2
|
nltk==3.9.2
|
||||||
pandas==3.0.0
|
numpy==2.4.2
|
||||||
|
pandas==3.0.1
|
||||||
|
psycopg2==2.9.11
|
||||||
|
psycopg2_binary==2.9.11
|
||||||
python-dotenv==1.2.1
|
python-dotenv==1.2.1
|
||||||
Requests==2.32.5
|
Requests==2.32.5
|
||||||
sentence_transformers==5.2.2
|
sentence_transformers==5.2.2
|
||||||
|
|||||||
@@ -1,15 +1,39 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
|
from flask_bcrypt import Bcrypt
|
||||||
|
from flask_jwt_extended import (
|
||||||
|
JWTManager,
|
||||||
|
create_access_token,
|
||||||
|
jwt_required,
|
||||||
|
get_jwt_identity
|
||||||
|
)
|
||||||
|
|
||||||
from server.stat_gen import StatGen
|
from server.stat_gen import StatGen
|
||||||
|
from db.database import PostgresConnector
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import traceback
|
import traceback
|
||||||
import json
|
import json
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
db = PostgresConnector()
|
||||||
|
|
||||||
# Allow for CORS from localhost:5173
|
# Env Variables
|
||||||
CORS(app, resources={r"/*": {"origins": "http://localhost:5173"}})
|
load_dotenv()
|
||||||
|
frontend_url = os.getenv("FRONTEND_URL", "http://localhost:5173")
|
||||||
|
jwt_secret_key = os.getenv("JWT_SECRET_KEY", "super-secret-change-this")
|
||||||
|
jwt_access_token_expires = int(os.getenv("JWT_ACCESS_TOKEN_EXPIRES", 1200)) # Default to 20 minutes
|
||||||
|
|
||||||
|
# Flask Configuration
|
||||||
|
CORS(app, resources={r"/*": {"origins": frontend_url}})
|
||||||
|
app.config["JWT_SECRET_KEY"] = jwt_secret_key
|
||||||
|
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = jwt_access_token_expires
|
||||||
|
|
||||||
|
bcrypt = Bcrypt(app)
|
||||||
|
jwt = JWTManager(app)
|
||||||
|
|
||||||
# Global State
|
# Global State
|
||||||
posts_df = pd.read_json('small.jsonl', lines=True)
|
posts_df = pd.read_json('small.jsonl', lines=True)
|
||||||
@@ -17,6 +41,22 @@ with open("topic_buckets.json", "r", encoding="utf-8") as f:
|
|||||||
domain_topics = json.load(f)
|
domain_topics = json.load(f)
|
||||||
stat_obj = StatGen(posts_df, domain_topics)
|
stat_obj = StatGen(posts_df, domain_topics)
|
||||||
|
|
||||||
|
@app.route('/register', methods=['POST'])
|
||||||
|
def register_user():
|
||||||
|
data = request.get_json()
|
||||||
|
|
||||||
|
if not data or "username" not in data or "password" not in data:
|
||||||
|
return jsonify({"error": "Missing username or password"}), 400
|
||||||
|
|
||||||
|
username = data["username"]
|
||||||
|
hashed_password = bcrypt.generate_password_hash(
|
||||||
|
data["password"]
|
||||||
|
).decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
print(f"Registered new user: {username}")
|
||||||
|
return jsonify({"message": f"User '{username}' registered successfully"}), 200
|
||||||
|
|
||||||
@app.route('/upload', methods=['POST'])
|
@app.route('/upload', methods=['POST'])
|
||||||
def upload_data():
|
def upload_data():
|
||||||
if "posts" not in request.files or "topics" not in request.files:
|
if "posts" not in request.files or "topics" not in request.files:
|
||||||
|
|||||||
12
server/auth.py
Normal file
12
server/auth.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from db.database import PostgresConnector
|
||||||
|
|
||||||
|
class AuthManager:
|
||||||
|
def __init__(self, db: PostgresConnector, bcrypt):
|
||||||
|
self.db = db
|
||||||
|
self.bcrypt = bcrypt
|
||||||
|
|
||||||
|
def register_user(self, username, password):
|
||||||
|
# Hash the password
|
||||||
|
hashed_password = self.bcrypt.generate_password_hash(password).decode("utf-8")
|
||||||
|
# Save the user to the database
|
||||||
|
self.db.save_user(username, hashed_password)
|
||||||
Reference in New Issue
Block a user