diff --git a/cmd/main.go b/cmd/main.go index 41bccfb..bbb762c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -34,6 +34,9 @@ func init() { func main() { defer internal.CloseLog() + http.HandleFunc("/", internal.LandingHandler) + http.HandleFunc("/login", internal.LoginHandler) + http.HandleFunc("/dash", internal.AuthClientMiddleware(internal.DashboardHandler)) http.HandleFunc("/upload", internal.AuthMiddleware(internal.UploadHandler)) http.HandleFunc("/health", internal.HealthHandler) diff --git a/internal/server.go b/internal/server.go index b0424ea..5d1efb1 100644 --- a/internal/server.go +++ b/internal/server.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strconv" "strings" + "text/template" "time" ) @@ -30,6 +31,106 @@ func SetShit() { UploadDir = os.Getenv("CCTV_UploadDir") } +func LandingHandler(w http.ResponseWriter, r *http.Request) { + content, err := os.ReadFile("views/index.html") + if err != nil { + http.Error(w, "Error reading file", http.StatusInternalServerError) + return + } + fmt.Fprint(w, string(content)) +} + +func LoginHandler(w http.ResponseWriter, r *http.Request) { + ip := getClientIP(r) + + mu.Lock() + + if banTime, banned := bannedIPs[ip]; banned { + fmt.Print("Banned IP: ", ip, " until ", banTime, "\n") + if time.Now().Before(banTime) { + bannedIPs[ip] = time.Now().Add(BanDuration) + http.Error(w, "You are banned", http.StatusForbidden) + mu.Unlock() + return + } + delete(bannedIPs, ip) + } + + mu.Unlock() + + username := r.FormValue("username") + password := r.FormValue("password") + + if username == "admin" && password == "admin" { + w.Header().Set("Authorization", "Bearer "+"hihi") + http.Redirect(w, r, "/dash", http.StatusSeeOther) + return + } else { + LogFailedAttempt(ip) + + mu.Lock() + failedAttempts[ip]++ + if failedAttempts[ip] >= MaxFailedAttempts { + bannedIPs[ip] = time.Now().Add(BanDuration) + delete(failedAttempts, ip) + + LogBan(ip) + } + mu.Unlock() + + http.Error(w, "Unauthorized", http.StatusUnauthorized) + } + +} + +func AuthClientMiddleware(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + authHeader := r.Header.Get("Authorization") + fmt.Print(authHeader) + if !strings.HasPrefix(authHeader, "Bearer ") || strings.TrimPrefix(authHeader, "Bearer ") != "hihi" { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + next(w, r) + } +} + +func DashboardHandler(w http.ResponseWriter, r *http.Request) { + // get the newest picture name + pictures, err := os.ReadDir(UploadDir) + if err != nil { + http.Error(w, "Error reading directory", http.StatusInternalServerError) + return + } + + if len(pictures) == 0 { + http.Error(w, "No pictures found", http.StatusNotFound) + return + } + + // get the newest picture + newestPicture := pictures[0] + for _, picture := range pictures { + pictureInfo, err := picture.Info() + if err != nil { + http.Error(w, "Error getting file info", http.StatusInternalServerError) + return + } + newestPictureInfo, err := newestPicture.Info() + if err != nil { + http.Error(w, "Error getting file info", http.StatusInternalServerError) + return + } + if pictureInfo.ModTime().After(newestPictureInfo.ModTime()) { + newestPicture = picture + } + } + + tmpl := template.Must(template.ParseFiles("views/dash.html")) + tmpl.Execute(w, newestPicture.Name()) +} + func UploadHandler(w http.ResponseWriter, r *http.Request) { err := r.ParseMultipartForm(10 << 20) if err != nil { diff --git a/views/dash.html b/views/dash.html new file mode 100644 index 0000000..7eeebe1 --- /dev/null +++ b/views/dash.html @@ -0,0 +1,10 @@ + + + + CCTV + + +

Latest Picture

+ Latest Picture + + \ No newline at end of file diff --git a/views/index.html b/views/index.html new file mode 100644 index 0000000..e24832e --- /dev/null +++ b/views/index.html @@ -0,0 +1,17 @@ + + + + CCTV + + +

CCTV

+

Login

+
+ + + + + +
+ + \ No newline at end of file