package webserver import ( "fmt" "log" "mime/multipart" "net/http" "strconv" "time" "git.tovijaeschke.xyz/tovi/personal_website/database" "git.tovijaeschke.xyz/tovi/personal_website/helper" "git.tovijaeschke.xyz/tovi/personal_website/variables" "github.com/gorilla/mux" "github.com/gorilla/sessions" "golang.org/x/crypto/bcrypt" ) func CheckAuth(w http.ResponseWriter, r *http.Request) bool { var ( session *sessions.Session lastLoginUnix int64 lastLogin time.Time auth bool exists bool e error ) session, e = variables.CookieStore.Get(r, variables.CookieName) if e != nil { return false } auth, exists = session.Values["authenticated"].(bool) if !(auth && exists) { return false } lastLoginUnix, exists = session.Values["lastLogin"].(int64) if !exists { return false } lastLogin = time.Unix(lastLoginUnix, 0) lastLogin = lastLogin.Add(3 * time.Hour) if time.Now().After(lastLogin) { session.Values = make(map[interface{}]interface{}) session.Values["authenticated"] = false session.AddFlash("Login Expired") e = session.Save(r, w) if e != nil { log.Println(e.Error()) } return false } return true } func AdminView(w http.ResponseWriter, r *http.Request) { var ( v = make(map[string]interface{}) urlParams map[string]string page string pageInt int pageOffset int posts []database.Post exists bool e error ) if !CheckAuth(w, r) { http.Redirect(w, r, "/admin/login", 302) return } switch r.Method { case http.MethodGet: urlParams = mux.Vars(r) page, exists = urlParams["page"] if exists { pageInt, e = strconv.Atoi(page) if e != nil { log.Fatal("Url Parameter page cannot be converted to an int") } } else { pageInt = 0 } pageOffset = pageInt * 10 posts, e = database.GetPostsList(10, pageOffset) v["Posts"] = posts ServeTemplate(w, r, "html/admin/admin-index.gohtml", v) return } } func comparePasswords(hashedPwd, plainPwd string) bool { var ( e error ) e = bcrypt.CompareHashAndPassword( []byte(hashedPwd), []byte(plainPwd), ) if e != nil { return false } return true } func AdminLogout(w http.ResponseWriter, r *http.Request) { var ( session *sessions.Session e error ) if !CheckAuth(w, r) { http.Redirect(w, r, "/admin/login", 302) return } session, e = variables.CookieStore.Get(r, variables.CookieName) if e != nil { log.Println("Could not get session cookie") http.Error(w, "Error", http.StatusInternalServerError) return } session.Values["authenticated"] = false session.Values["lastLogin"] = nil session.Save(r, w) http.Redirect(w, r, "/admin/logout", 302) return } func AdminLogin(w http.ResponseWriter, r *http.Request) { var ( session *sessions.Session v = make(map[string]interface{}) flashes []interface{} username string password string e error ) if CheckAuth(w, r) { http.Redirect(w, r, "/admin", 302) return } session, e = variables.CookieStore.Get(r, variables.CookieName) if e != nil { log.Println("Could not get session cookie") http.Error(w, "Error", http.StatusInternalServerError) return } switch r.Method { case http.MethodGet: flashes = session.Flashes() e = session.Save(r, w) if e != nil { log.Println(e.Error()) return } if len(flashes) > 0 { v["FlashMsg"] = flashes[0].(string) } ServeTemplate(w, r, "html/admin/admin-login.gohtml", v) return case http.MethodPost: e = r.ParseForm() if e != nil { log.Println(e.Error()) http.Redirect(w, r, "/login", 302) } username = r.FormValue("username") password = r.FormValue("password") if username != variables.AdminPassword && !comparePasswords(variables.AdminPassword, password) { session.AddFlash("Invalid Username or Password") e = session.Save(r, w) if e != nil { log.Println(e.Error()) } http.Redirect(w, r, "/admin/login", 302) return } session.Values["authenticated"] = true session.Values["lastLogin"] = time.Now().Unix() session.Save(r, w) http.Redirect(w, r, "/admin", 302) return } } func AdminNewPost(w http.ResponseWriter, r *http.Request) { var ( session *sessions.Session v = make(map[string]interface{}) flashes []interface{} title, subject, intro, body string bodyPath string mainFilePath string = "" fileUpload []*multipart.FileHeader //otherImgs string e error ) if !CheckAuth(w, r) { http.Redirect(w, r, "/admin/login", 302) return } session, e = variables.CookieStore.Get(r, variables.CookieName) if e != nil { log.Println("Could not get session cookie") http.Error(w, "Error", http.StatusInternalServerError) return } switch r.Method { case http.MethodGet: flashes = session.Flashes() e = session.Save(r, w) if e != nil { log.Println(e.Error()) return } if len(flashes) > 0 { v["FlashMsg"] = flashes[0].(string) } ServeTemplate(w, r, "html/admin/admin-new-post.gohtml", v) return case http.MethodPost: title = r.FormValue("title") subject = r.FormValue("subject") intro = r.FormValue("intro") body = r.FormValue("body") bodyPath, e = helper.WriteBody(title, body) if e != nil { log.Fatal(e) } r.ParseMultipartForm(32 << 20) // 32MB is the default used by FormFile fileUpload = r.MultipartForm.File["img"] helper.UploadFiles(fileUpload) if len(fileUpload) == 1 { mainFilePath = fileUpload[0].Filename } fileUpload = r.MultipartForm.File["files"] helper.UploadFiles(fileUpload) database.CreatePost( database.Post{ Title: title, Subject: subject, Intro: intro, HtmlPath: bodyPath, MainImage: mainFilePath, }, ) http.Redirect(w, r, "/admin", 302) return } } func AdminEditPost(w http.ResponseWriter, r *http.Request) { var ( session *sessions.Session v = make(map[string]interface{}) urlParams map[string]string flashes []interface{} title, subject, intro, body string bodyPath string post database.Post fileUpload []*multipart.FileHeader e error ) if !CheckAuth(w, r) { http.Redirect(w, r, "/admin/login", 302) return } session, e = variables.CookieStore.Get(r, variables.CookieName) if e != nil { log.Println("Could not get session cookie") http.Error(w, "Error", http.StatusInternalServerError) return } switch r.Method { case http.MethodGet: flashes = session.Flashes() e = session.Save(r, w) if e != nil { log.Println(e.Error()) return } if len(flashes) > 0 { v["FlashMsg"] = flashes[0].(string) } urlParams = mux.Vars(r) post, e = database.GetPostById(urlParams["id"]) if e != nil { log.Fatal("Cannot get Post by id") } post.Body, e = helper.GetFileContents(post.HtmlPath) if e != nil { log.Fatal("Cannot read body file") } v["Post"] = post ServeTemplate(w, r, "html/admin/admin-update-post.gohtml", v) return case http.MethodPost: urlParams = mux.Vars(r) post, e = database.GetPostById(urlParams["id"]) if e != nil { log.Fatal("Cannot get Post by id") } title = r.FormValue("title") subject = r.FormValue("subject") intro = r.FormValue("intro") body = r.FormValue("body") if title != post.Title { defer helper.DeleteOldPostFile(post.Title) } bodyPath, e = helper.WriteBody(title, body) if e != nil { log.Fatal(e) } r.ParseMultipartForm(32 << 20) // 32MB is the default used by FormFile fileUpload = r.MultipartForm.File["img"] helper.UploadFiles(fileUpload) if len(fileUpload) == 1 { post.MainImage = fileUpload[0].Filename } fileUpload = r.MultipartForm.File["files"] helper.UploadFiles(fileUpload) post.Title = title post.Subject = subject post.Intro = intro post.HtmlPath = bodyPath database.UpdatePost( post, ) http.Redirect(w, r, fmt.Sprintf("/admin/post/%s/edit", post.ID), 302) return } }