admin core func done
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
@@ -89,13 +90,6 @@ func clearSessionCookie(w http.ResponseWriter) {
|
||||
})
|
||||
}
|
||||
|
||||
// func LoginPage(w http.ResponseWriter, r *http.Request) {
|
||||
// utils.Render(w, "login.html", map[string]interface{}{
|
||||
// "Title": "Login",
|
||||
// "IsAuthenticated": false,
|
||||
// })
|
||||
// }
|
||||
|
||||
func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
@@ -107,7 +101,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Input validation
|
||||
if email == "" || password == "" {
|
||||
renderLoginError(w, "Email and password are required")
|
||||
http.Redirect(w, r, "/?error=EmailAndPasswordRequired", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,7 +118,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Login failed for email %s: %v", email, err)
|
||||
renderLoginError(w, "Invalid email or password")
|
||||
http.Redirect(w, r, "/?error=InvalidCredentials", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -132,7 +126,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err = bcrypt.CompareHashAndPassword([]byte(storedHash), []byte(password))
|
||||
if err != nil {
|
||||
log.Printf("Password verification failed for user ID %d", userID)
|
||||
renderLoginError(w, "Invalid email or password")
|
||||
http.Redirect(w, r, "/?error=InvalidCredentials", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -140,7 +134,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
tokenString, expirationTime, err := createJWTToken(userID, role)
|
||||
if err != nil {
|
||||
log.Printf("JWT token creation failed for user ID %d: %v", userID, err)
|
||||
http.Error(w, "Could not log in", http.StatusInternalServerError)
|
||||
http.Redirect(w, r, "/?error=InternalError", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -153,6 +147,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, redirectURL, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
|
||||
func RegisterHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
utils.Render(w, "register.html", map[string]interface{}{
|
||||
@@ -168,6 +163,7 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) {
|
||||
phone := r.FormValue("phone")
|
||||
role := r.FormValue("role")
|
||||
password := r.FormValue("password")
|
||||
adminCode := r.FormValue("admin_code") // for volunteers
|
||||
|
||||
// Input validation
|
||||
if firstName == "" || lastName == "" || email == "" || password == "" || role == "" {
|
||||
@@ -183,185 +179,66 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Insert user into database
|
||||
_, err = models.DB.Exec(`
|
||||
INSERT INTO "users" (first_name, last_name, email, phone, password, role_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
`, firstName, lastName, email, phone, string(hashedPassword), role)
|
||||
|
||||
// Convert role to int
|
||||
roleID, err := strconv.Atoi(role)
|
||||
if err != nil {
|
||||
log.Printf("User registration failed for email %s: %v", email, err)
|
||||
renderRegisterError(w, "Invalid role")
|
||||
return
|
||||
}
|
||||
|
||||
var adminID int
|
||||
if roleID == 3 { // volunteer
|
||||
if adminCode == "" {
|
||||
renderRegisterError(w, "Admin code is required for volunteers")
|
||||
return
|
||||
}
|
||||
|
||||
// Check if admin exists
|
||||
err = models.DB.QueryRow(`SELECT user_id FROM users WHERE role_id = 1 AND admin_code = $1`, adminCode).Scan(&adminID)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
renderRegisterError(w, "Invalid admin code")
|
||||
return
|
||||
}
|
||||
log.Printf("DB error checking admin code: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Insert user and get ID
|
||||
var userID int
|
||||
err = models.DB.QueryRow(`
|
||||
INSERT INTO users (first_name, last_name, email, phone, password, role_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING user_id
|
||||
`, firstName, lastName, email, phone, string(hashedPassword), roleID).Scan(&userID)
|
||||
if err != nil {
|
||||
log.Printf("User registration failed: %v", err)
|
||||
renderRegisterError(w, "Could not create account. Email might already be in use.")
|
||||
return
|
||||
}
|
||||
|
||||
// Link volunteer to admin if role is volunteer
|
||||
if roleID == 3 {
|
||||
_, err = models.DB.Exec(`
|
||||
INSERT INTO admin_volunteers (admin_id, volunteer_id)
|
||||
VALUES ($1, $2)
|
||||
`, adminID, userID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to link volunteer to admin: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("User registered successfully: %s %s (%s)", firstName, lastName, email)
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
clearSessionCookie(w)
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// // Admin Dashboard Handler
|
||||
// func AdminDashboardHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// role := r.Context().Value("user_role").(int)
|
||||
// userID := r.Context().Value("user_id").(int)
|
||||
|
||||
// // TODO: Fetch real data from database
|
||||
// dashboardData := map[string]interface{}{
|
||||
// "UserID": userID,
|
||||
// "TotalUsers": 100, // Example: get from database
|
||||
// "TotalVolunteers": 50, // Example: get from database
|
||||
// "TotalAddresses": 200, // Example: get from database
|
||||
// "RecentActivity": []string{"User logged in", "New volunteer registered"}, // Example
|
||||
// }
|
||||
|
||||
// data := createTemplateData("Admin Dashboard", "dashboard", role, true, dashboardData)
|
||||
// utils.Render(w, "dashboard/dashboard.html", data)
|
||||
// }
|
||||
|
||||
// // Volunteer Management Handler
|
||||
// func VolunteerHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// role := r.Context().Value("user_role").(int)
|
||||
|
||||
// // TODO: Fetch real volunteer data from database
|
||||
// volunteerData := map[string]interface{}{
|
||||
// "Volunteers": []map[string]interface{}{
|
||||
// {"ID": 1, "Name": "John Doe", "Email": "john@example.com", "Status": "Active"},
|
||||
// {"ID": 2, "Name": "Jane Smith", "Email": "jane@example.com", "Status": "Active"},
|
||||
// }, // Example: get from database
|
||||
// }
|
||||
|
||||
// data := createTemplateData("Volunteers", "volunteer", role, true, volunteerData)
|
||||
// utils.Render(w, "volunteers/volunteers.html", data)
|
||||
// }
|
||||
|
||||
// // Address Management Handler
|
||||
// func AddressHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// role := r.Context().Value("user_role").(int)
|
||||
|
||||
// // TODO: Fetch real address data from database
|
||||
// addressData := map[string]interface{}{
|
||||
// "Addresses": []map[string]interface{}{
|
||||
// {"ID": 1, "Street": "123 Main St", "City": "Calgary", "Status": "Validated"},
|
||||
// {"ID": 2, "Street": "456 Oak Ave", "City": "Calgary", "Status": "Pending"},
|
||||
// }, // Example: get from database
|
||||
// }
|
||||
|
||||
// data := createTemplateData("Addresses", "address", role, true, addressData)
|
||||
// utils.Render(w, "addresses/addresses.html", data)
|
||||
// }
|
||||
|
||||
// // Reports Handler
|
||||
// func ReportHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// role := r.Context().Value("user_role").(int)
|
||||
|
||||
// // TODO: Fetch real report data from database
|
||||
// reportData := map[string]interface{}{
|
||||
// "Reports": []map[string]interface{}{
|
||||
// {"ID": 1, "Name": "Weekly Summary", "Date": "2025-08-25", "Status": "Complete"},
|
||||
// {"ID": 2, "Name": "Monthly Analytics", "Date": "2025-08-01", "Status": "Pending"},
|
||||
// }, // Example: get from database
|
||||
// }
|
||||
|
||||
// data := createTemplateData("Reports", "report", role, true, reportData)
|
||||
// utils.Render(w, "reports/reports.html", data)
|
||||
// }
|
||||
|
||||
// // Profile Handler (works for both admin and volunteer)
|
||||
// func ProfileHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// role := r.Context().Value("user_role").(int)
|
||||
// userID := r.Context().Value("user_id").(int)
|
||||
|
||||
// // Fetch real user data from database
|
||||
// var firstName, lastName, email, phone string
|
||||
// err := models.DB.QueryRow(`
|
||||
// SELECT first_name, last_name, email, phone
|
||||
// FROM "users"
|
||||
// WHERE user_id = $1
|
||||
// `, userID).Scan(&firstName, &lastName, &email, &phone)
|
||||
|
||||
// profileData := map[string]interface{}{
|
||||
// "UserID": userID,
|
||||
// }
|
||||
|
||||
// if err != nil {
|
||||
// log.Printf("Error fetching user profile for ID %d: %v", userID, err)
|
||||
// profileData["Error"] = "Could not load profile data"
|
||||
// } else {
|
||||
// profileData["FirstName"] = firstName
|
||||
// profileData["LastName"] = lastName
|
||||
// profileData["Email"] = email
|
||||
// profileData["Phone"] = phone
|
||||
// }
|
||||
|
||||
// data := createTemplateData("Profile", "profile", role, true, profileData)
|
||||
// utils.Render(w, "profile/profile.html", data)
|
||||
// }
|
||||
|
||||
// // Volunteer Dashboard Handler
|
||||
// func VolunteerDashboardHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// role := r.Context().Value("user_role").(int)
|
||||
// userID := r.Context().Value("user_id").(int)
|
||||
|
||||
// // TODO: Fetch volunteer-specific data from database
|
||||
// dashboardData := map[string]interface{}{
|
||||
// "UserID": userID,
|
||||
// "AssignedTasks": 5, // Example: get from database
|
||||
// "CompletedTasks": 12, // Example: get from database
|
||||
// "UpcomingEvents": []string{"Community Meeting - Aug 30", "Training Session - Sep 5"}, // Example
|
||||
// }
|
||||
|
||||
// data := createTemplateData("Volunteer Dashboard", "dashboard", role, true, dashboardData)
|
||||
// utils.Render(w, "volunteer/dashboard.html", data)
|
||||
// }
|
||||
|
||||
// // Schedule Handler for Volunteers
|
||||
// func ScheduleHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// role := r.Context().Value("user_role").(int)
|
||||
// userID := r.Context().Value("user_id").(int)
|
||||
|
||||
// // TODO: Fetch schedule data from database
|
||||
// scheduleData := map[string]interface{}{
|
||||
// "UserID": userID,
|
||||
// "Schedule": []map[string]interface{}{
|
||||
// {"Date": "2025-08-26", "Time": "10:00 AM", "Task": "Door-to-door survey", "Location": "Downtown"},
|
||||
// {"Date": "2025-08-28", "Time": "2:00 PM", "Task": "Data entry", "Location": "Office"},
|
||||
// }, // Example: get from database
|
||||
// }
|
||||
|
||||
// data := createTemplateData("My Schedule", "schedual", role, true, scheduleData)
|
||||
// utils.Render(w, "volunteer/schedule.html", data)
|
||||
// }
|
||||
|
||||
// Enhanced middleware to check JWT auth and add user context
|
||||
func AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie("session")
|
||||
if err != nil {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
claims := &models.Claims{}
|
||||
token, err := jwt.ParseWithClaims(cookie.Value, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwtKey, nil
|
||||
})
|
||||
|
||||
if err != nil || !token.Valid {
|
||||
log.Printf("Invalid token: %v", err)
|
||||
clearSessionCookie(w) // Clear invalid cookie
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Add user info to context
|
||||
ctx := context.WithValue(r.Context(), "user_id", claims.UserID)
|
||||
ctx = context.WithValue(ctx, "user_role", claims.Role)
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user