diff --git a/develop.go b/develop.go index 1a552b2..e5417ce 100644 --- a/develop.go +++ b/develop.go @@ -4,6 +4,10 @@ package main const port = 8080 +func getSecret() string { + return "test" +} + func getDbPath() string { return "db.sqlite" } diff --git a/internal/server/handler.go b/internal/server/handler.go index 5a1da94..a0d0936 100644 --- a/internal/server/handler.go +++ b/internal/server/handler.go @@ -18,6 +18,26 @@ import ( "time" ) +func (s *Server) HandleLoginPost(w http.ResponseWriter, r *http.Request) { + fmt.Println("Setting auth") + secret := r.PostFormValue("secret") + http.SetCookie(w, &http.Cookie{ + Name: "auth", + Value: secret, + Path: "/", + MaxAge: 3600, + Secure: true, + HttpOnly: false, + SameSite: http.SameSiteLaxMode, + }) + http.Redirect(w, r, "/", http.StatusFound) +} + +func (s *Server) HandleLogin(w http.ResponseWriter, r *http.Request) { + tmpl := template.Must(view.GetViewTemplate(view.Login)) + tmpl.Execute(w, nil) +} + func (s *Server) HandleNew(w http.ResponseWriter, r *http.Request) { title := r.PathValue("title") chapter := r.PathValue("chapter") @@ -32,7 +52,7 @@ func (s *Server) HandleNew(w http.ResponseWriter, r *http.Request) { go s.LoadNext() go s.LoadPrev() - http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/current/", http.StatusFound) } func (s *Server) HandleMenu(w http.ResponseWriter, _ *http.Request) { @@ -159,24 +179,24 @@ func (s *Server) HandleDelete(w http.ResponseWriter, r *http.Request) { mangaStr := r.PostFormValue("mangaId") if mangaStr == "" { - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) return } mangaId, err := strconv.Atoi(mangaStr) if err != nil { fmt.Println(err) - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) return } s.DbMgr.Delete(mangaId) - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) } func (s *Server) HandleExit(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) go func() { s.Mutex.Lock() @@ -284,7 +304,7 @@ func (s *Server) HandleNext(w http.ResponseWriter, r *http.Request) { } if s.NextViewModel == nil || s.NextSubUrl == "" { - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) return } @@ -295,7 +315,7 @@ func (s *Server) HandleNext(w http.ResponseWriter, r *http.Request) { go s.LoadNext() - http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/current/", http.StatusFound) } func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) { fmt.Println("Received Prev") @@ -311,7 +331,7 @@ func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) { } if s.PrevViewModel == nil || s.PrevSubUrl == "" { - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) return } @@ -322,7 +342,7 @@ func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) { go s.LoadPrev() - http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/current/", http.StatusFound) } func (s *Server) HandleSettingSet(w http.ResponseWriter, r *http.Request) { @@ -339,7 +359,7 @@ func (s *Server) HandleSettingSet(w http.ResponseWriter, r *http.Request) { s.DbMgr.Db.Model(&setting).Update("value", settingValue) } - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) } func (s *Server) HandleSetting(w http.ResponseWriter, r *http.Request) { @@ -356,7 +376,7 @@ func (s *Server) HandleSetting(w http.ResponseWriter, r *http.Request) { s.DbMgr.Db.Model(&setting).Update("value", settingValue) } - http.Redirect(w, r, "/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/", http.StatusFound) } func (s *Server) HandleNewQuery(w http.ResponseWriter, r *http.Request) { @@ -372,5 +392,5 @@ func (s *Server) HandleNewQuery(w http.ResponseWriter, r *http.Request) { go s.LoadNext() go s.LoadPrev() - http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect) + http.Redirect(w, r, "/current/", http.StatusFound) } diff --git a/internal/server/middleware.go b/internal/server/middleware.go new file mode 100644 index 0000000..c9130ad --- /dev/null +++ b/internal/server/middleware.go @@ -0,0 +1,24 @@ +package server + +import ( + "net/http" +) + +func (s *Server) Auth(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie("auth") + if err != nil { + if r.URL.Path == "/login" || r.URL.Path == "/login/" { + next.ServeHTTP(w, r) + return + } + http.Redirect(w, r, "/login", http.StatusFound) + return + } + if cookie.Value == s.secret { + next.ServeHTTP(w, r) + } else { + http.Redirect(w, r, "/login", http.StatusFound) + } + }) +} diff --git a/internal/server/server.go b/internal/server/server.go index a0e9532..ffcd756 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -34,32 +34,39 @@ type Server struct { IsLast bool DbMgr *database.Manager + + secret string + mux *http.ServeMux } -func New(provider provider.Provider, db *database.Manager) *Server { +func New(provider provider.Provider, db *database.Manager, mux *http.ServeMux, secret string) *Server { s := Server{ ImageBuffers: make(map[string][]byte), Provider: provider, DbMgr: db, Mutex: &sync.Mutex{}, + mux: mux, + secret: secret, } return &s } func (s *Server) Start(port int) error { - http.HandleFunc("/", s.HandleMenu) - http.HandleFunc("/new/", s.HandleNewQuery) - http.HandleFunc("/new/title/{title}/{chapter}", s.HandleNew) - http.HandleFunc("/current/", s.HandleCurrent) - http.HandleFunc("/img/{url}/", s.HandleImage) - http.HandleFunc("POST /next", s.HandleNext) - http.HandleFunc("POST /prev", s.HandlePrev) - http.HandleFunc("POST /exit", s.HandleExit) - http.HandleFunc("POST /delete", s.HandleDelete) - http.HandleFunc("/favicon.ico", s.HandleFavicon) - http.HandleFunc("POST /setting/", s.HandleSetting) - http.HandleFunc("GET /setting/set/{setting}/{value}", s.HandleSettingSet) + s.mux.HandleFunc("GET /login", s.HandleLogin) + s.mux.HandleFunc("POST /login", s.HandleLoginPost) + s.mux.HandleFunc("/", s.HandleMenu) + s.mux.HandleFunc("/new/", s.HandleNewQuery) + s.mux.HandleFunc("/new/title/{title}/{chapter}", s.HandleNew) + s.mux.HandleFunc("/current/", s.HandleCurrent) + s.mux.HandleFunc("/img/{url}/", s.HandleImage) + s.mux.HandleFunc("POST /next", s.HandleNext) + s.mux.HandleFunc("POST /prev", s.HandlePrev) + s.mux.HandleFunc("POST /exit", s.HandleExit) + s.mux.HandleFunc("POST /delete", s.HandleDelete) + s.mux.HandleFunc("/favicon.ico", s.HandleFavicon) + s.mux.HandleFunc("POST /setting/", s.HandleSetting) + s.mux.HandleFunc("GET /setting/set/{setting}/{value}", s.HandleSettingSet) // Update Latest Chapters every 5 Minutes go func(s *Server) { @@ -96,8 +103,12 @@ func (s *Server) Start(port int) error { }(s) fmt.Println("Server starting...") - err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) - return err + + server := http.Server{ + Addr: fmt.Sprintf(":%d", port), + Handler: s.Auth(s.mux), + } + return server.ListenAndServe() } func (s *Server) LoadNext() { diff --git a/internal/view/Views/login.gohtml b/internal/view/Views/login.gohtml new file mode 100644 index 0000000..743fe91 --- /dev/null +++ b/internal/view/Views/login.gohtml @@ -0,0 +1,16 @@ + + + + + + + + +
+ + +
+ diff --git a/internal/view/embedded.go b/internal/view/embedded.go index bce7e16..7311521 100644 --- a/internal/view/embedded.go +++ b/internal/view/embedded.go @@ -14,12 +14,17 @@ var menu string //go:embed Views/viewer.gohtml var viewer string +//go:embed Views/login.gohtml +var login string + func GetViewTemplate(view View) (*template.Template, error) { switch view { case Menu: return template.New("menu").Parse(menu) case Viewer: return template.New("viewer").Parse(viewer) + case Login: + return template.New("login").Parse(login) } return nil, errors.New("invalid view") } diff --git a/internal/view/hotreload.go b/internal/view/hotreload.go index 62d0f7f..80960de 100644 --- a/internal/view/hotreload.go +++ b/internal/view/hotreload.go @@ -13,6 +13,8 @@ func GetViewTemplate(view View) (*template.Template, error) { path = "internal/view/Views/menu.gohtml" case Viewer: path = "internal/view/Views/viewer.gohtml" + case Login: + path = "internal/view/Views/login.gohtml" } return template.ParseFiles(path) } diff --git a/internal/view/views.go b/internal/view/views.go index 6d52763..982f305 100644 --- a/internal/view/views.go +++ b/internal/view/views.go @@ -5,4 +5,5 @@ type View int const ( Menu View = iota Viewer View = iota + Login View = iota ) diff --git a/main.go b/main.go index 7b43fe8..5cc7606 100644 --- a/main.go +++ b/main.go @@ -2,14 +2,16 @@ package main import ( "fmt" - "github.com/pablu23/mangaGetter/internal/database" - "github.com/pablu23/mangaGetter/internal/provider" - "github.com/pablu23/mangaGetter/internal/server" + "net/http" "os" "os/exec" "os/signal" "runtime" "time" + + "github.com/pablu23/mangaGetter/internal/database" + "github.com/pablu23/mangaGetter/internal/provider" + "github.com/pablu23/mangaGetter/internal/server" ) func main() { @@ -22,7 +24,9 @@ func main() { return } - s := server.New(&provider.Bato{}, &db) + secret := getSecret() + mux := http.NewServeMux() + s := server.New(&provider.Bato{}, &db, mux, secret) c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) diff --git a/release.go b/release.go index 73eb8b2..e14f0d0 100644 --- a/release.go +++ b/release.go @@ -9,6 +9,21 @@ import ( const port = 8000 +func getSecret() string { + dir, err := os.UserCacheDir() + if err != nil { + panic(err) + } + + dirPath := filepath.Join(dir, "MangaGetter") + filePath := filepath.Join(dirPath, "secret.secret") + buf, err := os.ReadFile(filePath) + if err != nil { + panic(err) + } + return string(buf) +} + func getDbPath() string { dir, err := os.UserCacheDir() if err != nil {