Skip to content
Open
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
17 changes: 17 additions & 0 deletions config/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from pymongo.mongo_client import MongoClient # type: ignore

uri = "mongodb+srv://admin1:cn242@cluster0.fum1o.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"

client = MongoClient(uri)
db = client["user_database"]
def get_collection(collection_name):
return db[collection_name]

users_collection = get_collection("users")
channels_collection = get_collection("channels")

try:
client.admin.command("ping")
print("Connected to MongoDB successfully!")
except Exception as e:
print("MongoDB connection error:", e)
29 changes: 29 additions & 0 deletions controller/authController.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import json
from models.authModel import UserRegister, UserLogin, Visitor
from services.authService import register_user, login_user, visitor_mode, logout_user

def register(data):
user = UserRegister(**data)
result = register_user(user)

return json.dumps(result)

def login(data, peer_ip, peer_port):
user = UserLogin(**data)
result = login_user(user, peer_ip, peer_port)
return json.dumps(result)


def visitor(data):
visitor_data = Visitor(**data)
result = visitor_mode(visitor_data)

return json.dumps(result)

def logout(data):
session_id = data.get("session_id")
if not session_id:
return json.dumps({"status": "error", "message": "Session ID is required"})

result = logout_user(session_id)
return json.dumps(result)
82 changes: 82 additions & 0 deletions controller/channelController
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@

from services.channelService import create_channel, join_channel, send_message, get_channel_info, get_joined_channels, get_hosted_channels, delete_channel, get_all_channels

##############################################################################################
def create_channel_controller(data):
host = data.get("host")
channel_name = data.get("channel_name")

if not host or not channel_name:
return {"status": "error", "message": "Missing parameters"}

result = create_channel(host, channel_name)
return result

##############################################################################################
def join_channel_controller(data):
username = data.get("username")
channel_name = data.get("channel_name")

if not username or not channel_name:
return {"status": "error", "message": "Missing parameters"}

result = join_channel(username, channel_name)
return result

##############################################################################################
def get_user_channels_controller(data):
username = data.get("username")

if not username:
return {"status": "error", "message": "Missing parameters"}

joined_result = get_joined_channels(username)
hosted_result = get_hosted_channels(username)

if joined_result["status"] == "error" or hosted_result["status"] == "error":
return {"status": "error", "message": "User not found"}

return {
"status": "success",
"data": {
"joined_channels": joined_result.get("joined_channels", []),
"hosted_channels": hosted_result.get("hosted_channels", [])
}
}

##############################################################################################
def send_message_controller(data):
username = data.get("username")
channel_name = data.get("channel_name")
message_text = data.get("message")

if not username or not channel_name or not message_text:
return {"status": "error", "message": "Missing parameters"}

result = send_message(username, channel_name, message_text)
return result

##############################################################################################
def get_channel_info_controller(data):
channel_name = data.get("channel_name")

if not channel_name:
return {"status": "error", "message": "Missing parameters"}

result = get_channel_info(channel_name)
return result
##############################################################################################
def delete_channel_controller(data):
username = data.get("username")
channel_name = data.get("channel_name")

if not username or not channel_name:
return {"status": "error", "message": "Missing parameters"}

result = delete_channel(username, channel_name)
return result

##############################################################################################
def get_all_channels_controller(data):
result = get_all_channels()
return result
17 changes: 17 additions & 0 deletions models/authModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from pydantic import BaseModel # type: ignore
from typing import List, Dict

class UserRegister(BaseModel):
username: str
email: str
password: str

class Visitor(BaseModel):
name: str

class UserLogin(BaseModel):
username: str
password: str
channels_joined: List[str] = []
hosted_channels: List[str] = []
sessions: List[Dict[str, str]] = []
Empty file added models/channelModel.py
Empty file.
86 changes: 86 additions & 0 deletions request/authRequest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from config.db import users_collection
import uuid
from datetime import datetime, timezone
from models.authModel import UserRegister, UserLogin, Visitor
##########################################################
def register_user(user: UserRegister) -> dict:
try:
if users_collection.find_one({"email": user.email}):
return {"status": "error", "message": "Email already registered"}

if users_collection.find_one({"username": user.username}):
return {"status": "error", "message": "Username already taken"}

new_user = user.model_dump()
new_user["verified"] = True

result = users_collection.insert_one(new_user)
return {"status": "success", "message": "User registered successfully", "user_id": str(result.inserted_id)}

except Exception as e:
return {"status": "error", "message": f"Database error: {str(e)}"}

##########################################################
def login_user(user: UserLogin, peer_ip: str, peer_port: int) -> dict:
user_data = users_collection.find_one({"username": user.username, "password": user.password})

if user_data:
session_id = str(uuid.uuid4())
new_session = {
"peer_ip": peer_ip,
"peer_port": peer_port,
"session_id": session_id,
"login_time": datetime.now(timezone.utc).isoformat()
}

users_collection.update_one(
{"username": user.username},
{"$push": {"sessions": new_session}}
)
user_data = users_collection.find_one({"username": user.username})

def serialize(obj):
if isinstance(obj, datetime):
return obj.isoformat()
return obj

return {
"status": "success",
"message": "Login successful",
"user": {
"username": user_data["username"],
"email": user_data.get("email", ""),
"channels_joined": user_data.get("channels_joined", []),
"hosted_channels": user_data.get("hosted_channels", []),
"sessions": [{**session, "login_time": serialize(session["login_time"])}
for session in user_data.get("sessions", [])]
}
}

return {"status": "error", "message": "Invalid username or password"}

##########################################################
def visitor_mode(visitor_data: Visitor, ) -> dict:
if users_collection.find_one({"username": visitor_data.name}):
return {"status": "error", "message": "Username already taken"}
if not visitor_data.name:
return {"status": "error", "message": "Visitor name cannot be empty"}

return {"status": "success", "message": f"Welcome, {visitor_data.name}! You are in visitor mode."}
##########################################################
def logout_user(session_id: str) -> dict:
try:
user = users_collection.find_one({"sessions.session_id": session_id})

if not user:
return {"status": "error", "message": "Invalid session_id"}

users_collection.update_one(
{"_id": user["_id"]},
{"$pull": {"sessions": {"session_id": session_id}}}
)

return {"status": "success", "message": "Logout successful"}

except Exception as e:
return {"status": "error", "message": f"Database error: {str(e)}"}
123 changes: 123 additions & 0 deletions request/channelRequest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
from config.db import channels_collection, users_collection
from models.channelModel import Channel
##############################################################################################
def create_channel(host: str, channel_name: str):
if channels_collection.find_one({"channel_name": channel_name}):
return {"status": "error", "message": "Channel already exists"}

new_channel = Channel(
channel_name=channel_name,
owner=host,
members=[host]
)

channels_collection.insert_one(new_channel.dict())

users_collection.update_one(
{"username": host},
{"$addToSet": {"hosted_channels": channel_name, "joined_channels": channel_name}}
)

return {"status": "success", "message": f"Channel '{channel_name}' created successfully"}

##############################################################################################
def join_channel(username: str, channel_name: str):
channel = channels_collection.find_one({"channel_name": channel_name})
if not channel:
return {"status": "error", "message": "Channel not found"}

if username in channel["members"]:
return {"status": "error", "message": "User already in channel"}

channels_collection.update_one(
{"channel_name": channel_name},
{"$push": {"members": username}}
)

users_collection.update_one(
{"username": username},
{"$addToSet": {"joined_channels": channel_name}}
)

return {"status": "success", "message": f"{username} joined '{channel_name}'"}

##############################################################################################
def send_message(username: str, channel_name: str, message_text: str):
channel_data = channels_collection.find_one({"channel_name": channel_name})
if not channel_data:
return {"status": "error", "message": "Channel not found"}

if username not in channel_data["members"]:
return {"status": "error", "message": "Only registered users can send messages"}

new_message = {"sender": username, "text": message_text}

channels_collection.update_one(
{"channel_name": channel_name},
{"$push": {"messages": new_message}}
)

return {"status": "success", "message": "Message sent successfully"}

##############################################################################################
def get_channel_info(channel_name: str) -> dict:
channel = channels_collection.find_one({"channel_name": channel_name})

if not channel:
return {"status": "error", "message": "Channel not found"}

return {
"status": "success",
"channel_name": channel["channel_name"],
"owner": channel["owner"],
"members": channel["members"],
"messages": channel.get("messages", [])
}
##############################################################################################
def get_joined_channels(username: str):
user_data = users_collection.find_one({"username": username}, {"joined_channels": 1, "_id": 0})
if not user_data:
return {"status": "error", "message": "User not found"}

return {"status": "success", "joined_channels": user_data.get("joined_channels", [])}

##############################################################################################
def get_hosted_channels(username: str):
user_data = users_collection.find_one({"username": username}, {"hosted_channels": 1, "_id": 0})
if not user_data:
return {"status": "error", "message": "User not found"}

return {"status": "success", "hosted_channels": user_data.get("hosted_channels", [])}
##############################################################################################
def delete_channel(username: str, channel_name: str):
channel = channels_collection.find_one({"channel_name": channel_name})

if not channel:
return {"status": "error", "message": "Channel not found"}

if channel["owner"] != username:
return {"status": "error", "message": "Only the owner can delete the channel"}

channels_collection.delete_one({"channel_name": channel_name})

users_collection.update_many(
{},
{
"$pull": {
"hosted_channels": channel_name,
"joined_channels": channel_name
}
}
)

return {"status": "success", "message": f"Channel '{channel_name}' deleted successfully"}
##############################################################################################
def get_all_channels():
channels = channels_collection.find({}, {"_id": 0, "channel_name": 1, "owner": 1})

all_channels = list(channels)

return {
"status": "success",
"data": all_channels
}
Loading