2025-08-26 14:13:09 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
|
|
|
|
|
"github.com/golang-jwt/jwt/v5"
|
2025-08-27 17:54:45 -06:00
|
|
|
"github.com/joho/godotenv"
|
2025-08-26 14:13:09 -06:00
|
|
|
|
|
|
|
|
"github.com/patel-mann/poll-system/app/internal/handlers"
|
|
|
|
|
"github.com/patel-mann/poll-system/app/internal/models"
|
|
|
|
|
"github.com/patel-mann/poll-system/app/internal/utils"
|
|
|
|
|
|
|
|
|
|
_ "github.com/lib/pq" // use PostgreSQL
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
2025-08-28 17:09:23 -06:00
|
|
|
err := godotenv.Load()
|
2025-08-27 17:54:45 -06:00
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("Error loading .env file: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jwtSecret := os.Getenv("JWT_SECRET")
|
|
|
|
|
var jwtKey = []byte(jwtSecret)
|
|
|
|
|
|
2025-08-26 14:13:09 -06:00
|
|
|
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) {
|
2025-08-27 17:54:45 -06:00
|
|
|
return jwtKey, nil
|
2025-08-26 14:13:09 -06:00
|
|
|
})
|
|
|
|
|
if err != nil || !token.Valid {
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Admin middleware to check if user has admin role
|
|
|
|
|
func adminMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
|
|
|
|
return authMiddleware(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
role, ok := r.Context().Value("user_role").(int)
|
|
|
|
|
if !ok || role != 1 {
|
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Volunteer middleware to check if user has volunteer role
|
|
|
|
|
func volunteerMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
|
|
|
|
return authMiddleware(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
role, ok := r.Context().Value("user_role").(int)
|
|
|
|
|
if !ok || (role != 3 && role != 2) {
|
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func HomeHandler(w http.ResponseWriter, r *http.Request) {
|
2025-09-05 15:39:06 -06:00
|
|
|
utils.Render(w, "dashboard.html", map[string]interface{}{
|
2025-08-28 17:09:23 -06:00
|
|
|
"Title": "Admin Dashboard",
|
|
|
|
|
"IsAuthenticated": false,
|
|
|
|
|
"ActiveSection": "dashboard",
|
|
|
|
|
})
|
2025-08-26 14:13:09 -06:00
|
|
|
}
|
|
|
|
|
func main() {
|
|
|
|
|
models.InitDB()
|
2025-09-11 16:54:30 -06:00
|
|
|
|
|
|
|
|
models.EmailMessage("hellow")
|
|
|
|
|
|
2025-08-28 17:09:23 -06:00
|
|
|
// Static file servers
|
2025-08-26 14:13:09 -06:00
|
|
|
fs := http.FileServer(http.Dir("static"))
|
|
|
|
|
http.Handle("/static/", http.StripPrefix("/static/", fs))
|
2025-09-11 16:54:30 -06:00
|
|
|
|
2025-08-28 17:09:23 -06:00
|
|
|
uploadsFs := http.FileServer(http.Dir("uploads"))
|
|
|
|
|
http.Handle("/uploads/", http.StripPrefix("/uploads/", uploadsFs))
|
2025-08-26 14:13:09 -06:00
|
|
|
|
|
|
|
|
// Public HTML Routes
|
|
|
|
|
http.HandleFunc("/", HomeHandler)
|
|
|
|
|
http.HandleFunc("/login", handlers.LoginHandler)
|
|
|
|
|
http.HandleFunc("/register", handlers.RegisterHandler)
|
|
|
|
|
|
|
|
|
|
//--- Protected HTML Routes
|
|
|
|
|
http.HandleFunc("/logout", authMiddleware(handlers.LogoutHandler))
|
|
|
|
|
|
|
|
|
|
// Common routes (both admin and volunteer can access)
|
|
|
|
|
http.HandleFunc("/profile", authMiddleware(handlers.ProfileHandler))
|
|
|
|
|
http.HandleFunc("/profile/update", authMiddleware(handlers.ProfileUpdateHandler))
|
|
|
|
|
|
|
|
|
|
//--- Admin-only routes
|
|
|
|
|
http.HandleFunc("/dashboard", adminMiddleware(handlers.AdminDashboardHandler))
|
|
|
|
|
http.HandleFunc("/volunteers", adminMiddleware(handlers.VolunteerHandler))
|
|
|
|
|
http.HandleFunc("/volunteer/edit", adminMiddleware(handlers.EditVolunteerHandler))
|
|
|
|
|
http.HandleFunc("/team_builder", adminMiddleware(handlers.TeamBuilderHandler))
|
2025-08-27 13:21:11 -06:00
|
|
|
http.HandleFunc("/team_builder/remove_volunteer", adminMiddleware(handlers.RemoveVolunteerHandler))
|
2025-08-26 14:13:09 -06:00
|
|
|
http.HandleFunc("/addresses", adminMiddleware(handlers.AddressHandler))
|
2025-08-27 13:21:11 -06:00
|
|
|
http.HandleFunc("/assign_address", adminMiddleware(handlers.AssignAddressHandler))
|
2025-08-28 00:15:10 -06:00
|
|
|
http.HandleFunc("/remove_assigned_address", adminMiddleware(handlers.RemoveAssignedAddressHandler))
|
2025-08-28 23:27:24 -06:00
|
|
|
http.HandleFunc("/addresses/upload-csv", adminMiddleware(handlers.CSVUploadHandler))
|
2025-09-03 14:35:47 -06:00
|
|
|
http.HandleFunc("/reports", adminMiddleware(handlers.ReportsHandler))
|
2025-08-26 14:13:09 -06:00
|
|
|
http.HandleFunc("/posts", adminMiddleware(handlers.PostsHandler))
|
|
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
// Assignment management routes (Admin only)
|
|
|
|
|
// API Routes
|
2025-09-03 14:35:47 -06:00
|
|
|
http.HandleFunc("/api/validated-addresses", handlers.GetValidatedAddressesHandler)
|
2025-09-11 16:54:30 -06:00
|
|
|
http.HandleFunc("/api/validated-addresses/stats", handlers.GetValidatedAddressesStatsHandler)
|
2025-09-03 14:35:47 -06:00
|
|
|
|
2025-09-11 16:54:30 -06:00
|
|
|
//--- Volunteer-only routes
|
2025-08-26 14:13:09 -06:00
|
|
|
http.HandleFunc("/volunteer/dashboard", volunteerMiddleware(handlers.VolunteerPostsHandler))
|
2025-09-11 16:54:30 -06:00
|
|
|
http.HandleFunc("/volunteer/addresses", volunteerMiddleware(handlers.VolunteerAppointmentHandler))
|
|
|
|
|
|
|
|
|
|
// Schedule/Availability routes (Volunteer only)
|
|
|
|
|
http.HandleFunc("/volunteer/schedule", volunteerMiddleware(handlers.VolunteerGetAvailabilityHandler))
|
|
|
|
|
http.HandleFunc("/volunteer/schedule/post", volunteerMiddleware(handlers.VolunteerPostScheduleHandler))
|
|
|
|
|
http.HandleFunc("/volunteer/schedule/delete", volunteerMiddleware(handlers.VolunteerDeleteScheduleHandler))
|
2025-08-26 14:13:09 -06:00
|
|
|
|
2025-08-28 17:09:23 -06:00
|
|
|
// Poll routes (volunteer only)
|
|
|
|
|
http.HandleFunc("/poll", volunteerMiddleware(handlers.PollHandler))
|
2025-09-11 16:54:30 -06:00
|
|
|
|
2025-09-05 15:39:06 -06:00
|
|
|
log.Println("Server started on http://localhost:8080")
|
2025-08-27 13:21:11 -06:00
|
|
|
log.Fatal(http.ListenAndServe("0.0.0.0:8080", nil))
|
2025-09-11 16:54:30 -06:00
|
|
|
}
|