You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

394 lines
8.0 KiB

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
}
}