Skip to content
Merged
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
Binary file modified .DS_Store
Binary file not shown.
22 changes: 22 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Use an official Python runtime as a parent image
FROM python:3.9-slim

# Set environment variable to force Python output to be unbuffered
ENV PYTHONUNBUFFERED=1

# Set the working directory to /app
WORKDIR /app

# Copy requirements.txt and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy the entire project into the container
COPY . .

# Expose port 5000 (Cloud Run sets the PORT env variable)
EXPOSE 8080

# Run the API Gateway.
# Cloud Run will set PORT, so we use that environment variable.
CMD ["sh", "-c", "python backend/api_gateway/api_gateway.py ${PORT:-8080}"]
Binary file modified backend/.DS_Store
Binary file not shown.
572 changes: 527 additions & 45 deletions backend/api_gateway/api_gateway.py

Large diffs are not rendered by default.

Binary file modified backend/core/__pycache__/config.cpython-312.pyc
Binary file not shown.
2 changes: 1 addition & 1 deletion backend/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Config:

# API Configuration
API_HOST = os.getenv('API_HOST', 'localhost')
API_PORT = int(os.getenv('API_PORT', 5001))
API_PORT = int(os.getenv('API_PORT', 8080))

# Redis Configuration
REDIS_HOST = os.getenv('REDIS_HOST', 'localhost')
Expand Down
70 changes: 70 additions & 0 deletions backend/data/story_tracking_schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
-- story_tracking_schema.sql
-- Schema for story tracking feature

-- Table for tracked stories
CREATE TABLE tracked_stories (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES auth.users(id),
keyword VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
last_updated TIMESTAMP NOT NULL DEFAULT NOW()
);

-- Table for articles related to tracked stories
CREATE TABLE tracked_story_articles (
tracked_story_id UUID REFERENCES tracked_stories(id) ON DELETE CASCADE,
news_id UUID REFERENCES news_articles(id) ON DELETE CASCADE,
added_at TIMESTAMP NOT NULL DEFAULT NOW(),
PRIMARY KEY (tracked_story_id, news_id)
);

-- Index for faster lookups
CREATE INDEX idx_tracked_stories_user_id ON tracked_stories(user_id);
CREATE INDEX idx_tracked_stories_keyword ON tracked_stories(keyword);
CREATE INDEX idx_tracked_story_articles_story_id ON tracked_story_articles(tracked_story_id);

-- RLS Policies for tracked_stories
ALTER TABLE tracked_stories ENABLE ROW LEVEL SECURITY;

-- Allow users to view only their own tracked stories
CREATE POLICY tracked_stories_select_policy ON tracked_stories
FOR SELECT USING (auth.uid() = user_id);

-- Allow users to insert their own tracked stories
CREATE POLICY tracked_stories_insert_policy ON tracked_stories
FOR INSERT WITH CHECK (auth.uid() = user_id);

-- Allow users to update only their own tracked stories
CREATE POLICY tracked_stories_update_policy ON tracked_stories
FOR UPDATE USING (auth.uid() = user_id);

-- Allow users to delete only their own tracked stories
CREATE POLICY tracked_stories_delete_policy ON tracked_stories
FOR DELETE USING (auth.uid() = user_id);

-- RLS Policies for tracked_story_articles
ALTER TABLE tracked_story_articles ENABLE ROW LEVEL SECURITY;

-- Allow users to view only articles related to their tracked stories
CREATE POLICY tracked_story_articles_select_policy ON tracked_story_articles
FOR SELECT USING (
tracked_story_id IN (
SELECT id FROM tracked_stories WHERE user_id = auth.uid()
)
);

-- Allow users to insert only articles related to their tracked stories
CREATE POLICY tracked_story_articles_insert_policy ON tracked_story_articles
FOR INSERT WITH CHECK (
tracked_story_id IN (
SELECT id FROM tracked_stories WHERE user_id = auth.uid()
)
);

-- Allow users to delete only articles related to their tracked stories
CREATE POLICY tracked_story_articles_delete_policy ON tracked_story_articles
FOR DELETE USING (
tracked_story_id IN (
SELECT id FROM tracked_stories WHERE user_id = auth.uid()
)
);
Binary file not shown.
42 changes: 39 additions & 3 deletions backend/microservices/auth_service.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
#!/usr/bin/env python3
"""
auth_service.py - Microservice for Authentication
Handles user authentication, JWT token generation, and user profile management.
Authentication Service Module

This microservice handles all authentication-related functionality including:
- User authentication and authorization
- JWT token generation and validation
- User profile management and storage
- Session handling

The service uses a file-based storage system for user data (users.txt)
and JWT tokens for maintaining user sessions. It provides RESTful endpoints
for user registration, login, and profile management.

Environment Variables:
JWT_SECRET_KEY: Secret key for JWT token generation (required)

Typical usage example:
POST /auth/login {'username': 'user', 'password': 'pass'}
GET /auth/profile with JWT token in Authorization header
"""

from flask import Flask, request, jsonify
Expand Down Expand Up @@ -35,7 +51,27 @@
], f)

def load_users():
"""Load users from the users.txt file"""
"""Load user data from the users.txt file.

This function reads the JSON-formatted user data from the users.txt file
and returns it as a Python list of dictionaries. Each dictionary contains
user information including id, username, password, email, and name.

Returns:
list: A list of dictionaries containing user data.
Each dictionary has the following structure:
{
'id': int,
'username': str,
'password': str,
'email': str,
'firstName': str,
'lastName': str
}

Raises:
Exception: If there's an error reading or parsing the users file.
"""
try:
with open(USERS_FILE, 'r') as f:
return json.load(f)
Expand Down
74 changes: 65 additions & 9 deletions backend/microservices/news_fetcher.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,61 @@
"""News Fetcher Service

This module is responsible for fetching news articles from the News API based on
keywords and managing the storage of fetched articles. It provides functionality
to search for news articles and optionally save them to files with session-based
organization.

The module uses the News API (https://newsapi.org/) as its primary data source
and supports session-based article management for multi-user scenarios.

Typical usage:
articles = fetch_news('technology')
write_to_file(articles, 'user_session_123')

Environment Variables Required:
NEWS_API_KEY: API key for accessing the News API service
"""

import os
import requests
from dotenv import load_dotenv
import json
from pathlib import Path
from backend.core.config import Config


# Load environment variables from .env file
# Load environment variables from .env file for configuration
load_dotenv()

# Get the News API key from environment variables
# Initialize the News API key from environment variables
NEWS_API_KEY = os.getenv('NEWS_API_KEY')

def fetch_news(keyword='', session_id=None):
# Define the News API endpoint and parameters
"""Fetch news articles from News API based on a keyword search.

This function queries the News API to retrieve articles matching the provided
keyword. It supports session-based tracking of requests and can handle empty
keyword searches.

Args:
keyword (str, optional): The search term to find relevant articles.
Defaults to empty string which returns top headlines.
session_id (str, optional): Unique identifier for the current user session.
Used for organizing saved articles. Defaults to None.

Returns:
list: A list of dictionaries containing article data with fields like
'title', 'description', 'url', etc. Returns None on error.

Raises:
requests.exceptions.RequestException: If there's an error communicating
with the News API.
"""
# Configure the News API endpoint and request parameters
url = "https://newsapi.org/v2/everything"
params = {
'q': keyword, # Use the keyword for search
'q': keyword, # Search query parameter
'apiKey': NEWS_API_KEY,
'pageSize': 10
'pageSize': 1 # Limit results to 10 articles per request
}

try:
Expand Down Expand Up @@ -52,17 +89,36 @@ def fetch_news(keyword='', session_id=None):
print(f"Error fetching news: {e}")

def write_to_file(articles, session_id=None):
# Define the file path with session_id
"""Save fetched news articles to a JSON file.

This function stores the provided articles in a JSON file, organizing them
by session ID. It creates the necessary directories if they don't exist.

Args:
articles (list): List of article dictionaries to save.
session_id (str, optional): Unique identifier for the current session.
Used to create a unique filename. Defaults to 'default' if None.

Returns:
None

Raises:
IOError: If there's an error writing to the file system.
"""
# Use default session ID if none provided
if not session_id:
session_id = 'default'

# Generate a unique filename using the session ID
file_name = f'{session_id}_news_data.json'

# Construct the full file path using the configured data directory
file_path = Config.NEWS_DATA_DIR / file_name
try:
# Write articles to the file in JSON format
# Save the articles as formatted JSON for better readability
with open(file_path, 'w') as file:
json.dump(articles, file, indent=4)
print(f"Articles saved to {file_path}")
print(f"Articles successfully saved to {file_path}")
except IOError as e:
print(f"Error writing to file: {e}")

Expand Down
Loading
Loading