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
64 changes: 63 additions & 1 deletion auth-server/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func getReportsHandler(c *gin.Context) {

var reports []Report
filter := bson.M{"user_id": userID}

cursor, err := reportsColl.Find(ctx, filter)
if err != nil {
if err == mongo.ErrNoDocuments {
Expand Down Expand Up @@ -191,4 +192,65 @@ func getReportsHandler(c *gin.Context) {
Message: "Reports fetched successfully",
Data: reports,
})
}
}

// New handler to get user information
func getUserInfoHandler(c *gin.Context) {
userID := c.GetString("userID")
log.Println("[DEBUG] Getting user info for userID:", userID)

ctx, cancel := context.WithTimeout(context.Background(), 25*time.Second)
defer cancel()

// Convert userID string to ObjectID
objectID, err := primitive.ObjectIDFromHex(userID)
if err != nil {
c.JSON(http.StatusBadRequest, ErrorResponse{
Error: "invalid_user_id",
Message: "Invalid user ID format",
})
return
}

// Find user by ID
var user User
err = usersColl.FindOne(ctx, bson.M{"_id": objectID}).Decode(&user)
if err != nil {
if err == mongo.ErrNoDocuments {
c.JSON(http.StatusNotFound, ErrorResponse{
Error: "user_not_found",
Message: "User not found",
})
return
}
c.JSON(http.StatusInternalServerError, ErrorResponse{
Error: "database_error",
Message: "Failed to fetch user information",
})
return
}

// Count number of reports (attacks) for this user
reportsCount, err := reportsColl.CountDocuments(ctx, bson.M{"user_id": userID})
if err != nil {
log.Println("[ERROR] Failed to count reports:", err)
// Continue even if count fails, just set to 0
reportsCount = 0
}

// Prepare response with user info
userInfo := map[string]interface{}{
"user_id": user.ID.Hex(),
"email": user.Email,
"first_name": user.FirstName,
"last_name": user.LastName,
"username": user.FirstName + " " + user.LastName,
"attacks_count": reportsCount,
"created_at": user.CreatedAt,
}

c.JSON(http.StatusOK, SuccessResponse{
Message: "User information fetched successfully",
Data: userInfo,
})
}
3 changes: 1 addition & 2 deletions auth-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ var (
)

func main() {

// Load Env Variables
err := godotenv.Load()
if err != nil {
Expand Down Expand Up @@ -70,6 +69,7 @@ func main() {
{
auth.POST("/signup", signupHandler)
auth.POST("/login", loginHandler)
auth.GET("/getUserInfo", authMiddleware(), getUserInfoHandler)
}
}

Expand Down Expand Up @@ -97,7 +97,6 @@ func conn_DB() error {
}

dbName := os.Getenv("DATABASE_NAME")

db = mongo_client.Database(dbName)
usersColl = db.Collection("auth")
reportsColl = db.Collection("reports")
Expand Down
46 changes: 28 additions & 18 deletions frontend/src/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { Link, useNavigate } from "react-router-dom";
import api from "../components/api";LayoutDashboard
import api from "../components/api";
import { Shield, Home, History, Info, UserCircle, LogOut, X, LayoutDashboard } from 'lucide-react';
import { handleError } from './utils';

Expand All @@ -15,46 +15,54 @@ const Navbar = () => {
navigate("/login");
}, 1500);
};

// State to manage the visibility of the profile card.
const [showProfileCard, setShowProfileCard] = useState(false);
const [userData, setUserData] = useState({});
const [userData, setUserData] = useState({
username: '',
email: '',
attacks_count: 0
});

const fetchUserData = async () => {
try {
const res = await api.get('/api/user/profile');
const res = await api.get('/api/auth/getUserInfo');
const data = await res.data;
setUserData(data);
if (data && data.data) {
setUserData(data.data);
}
} catch (err) {
handleError('Error fetching user data:', err);
setTimeout(() => {
Logout();
navigate("/login");
}, 1500);
}
};

// Fetch user data when component mounts
useEffect(() => {
fetchUserData();
}, []);

// The main JSX for the Navbar.
return (
<nav className="fixed top-0 inset-x-0 z-20 bg-black/40 backdrop-blur-md rounded-b-xl px-6 py-4 shadow-xl">
<div className="container mx-auto flex items-center justify-between">
{/* Logo/App Title */}
<a href="#" className="flex items-center text-white text-xl font-bold tracking-wider">
<a className="flex items-center text-white text-xl font-bold tracking-wider" href="#">
<Shield className="w-8 h-8 mr-2 text-green-400" />
VULN<span className="text-green-400">ORA</span>
</a>

{/* Navigation Links */}
<div className="flex items-center space-x-6">
<Link to="/" className="flex items-center text-gray-400 hover:text-green-400 transition-colors">
<Link className="flex items-center text-gray-400 hover:text-green-400 transition-colors" to="/">
<Home className="w-5 h-5 mr-1" /> Home
</Link>
<Link to="/home" className="flex items-center text-gray-400 hover:text-green-400 transition-colors">
<Link className="flex items-center text-gray-400 hover:text-green-400 transition-colors" to="/home">
<LayoutDashboard className="w-5 h-5 mr-1" /> Dashboard
</Link>
<Link to="/history" className="flex items-center text-gray-400 hover:text-green-400 transition-colors">
<Link className="flex items-center text-gray-400 hover:text-green-400 transition-colors" to="/history">
<History className="w-5 h-5 mr-1" /> History
</Link>
<Link to="/#about" className="flex items-center text-gray-400 hover:text-green-400 transition-colors">
<Link className="flex items-center text-gray-400 hover:text-green-400 transition-colors" to="/#about">
<Info className="w-5 h-5 mr-1" /> About
</Link>
</div>
Expand Down Expand Up @@ -82,15 +90,17 @@ const Navbar = () => {
<div className="flex items-center mb-4">
<UserCircle className="w-10 h-10 text-green-400 mr-3" />
<div>
<h4 className="font-bold text-lg">{userData.firstName}</h4>
<p className="text-xs text-gray-400">{userData.email}</p>
<h4 className="font-bold text-lg">{userData.username || 'User'}</h4>
<p className="text-xs text-gray-400">{userData.email || ''}</p>
</div>
</div>

<div className="text-sm border-t border-gray-700 pt-3 mb-3">
<p className="text-gray-300">Scans Completed: <span className="text-green-400 font-semibold">
{/* {userData.scansDone} */} XX {/*TODO: replace with actual value*/}
<p className="text-gray-300">Attacks Run: <span className="text-green-400 font-semibold">
{userData.attacks_count || 0}
</span></p>
</div>

<button
onClick={() => {
Logout();
Expand Down