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

  1. package webserver
  2. import (
  3. "fmt"
  4. "log"
  5. "mime/multipart"
  6. "net/http"
  7. "strconv"
  8. "time"
  9. "git.tovijaeschke.xyz/tovi/personal_website/database"
  10. "git.tovijaeschke.xyz/tovi/personal_website/helper"
  11. "git.tovijaeschke.xyz/tovi/personal_website/variables"
  12. "github.com/gorilla/mux"
  13. "github.com/gorilla/sessions"
  14. "golang.org/x/crypto/bcrypt"
  15. )
  16. func CheckAuth(w http.ResponseWriter, r *http.Request) bool {
  17. var (
  18. session *sessions.Session
  19. lastLoginUnix int64
  20. lastLogin time.Time
  21. auth bool
  22. exists bool
  23. e error
  24. )
  25. session, e = variables.CookieStore.Get(r, variables.CookieName)
  26. if e != nil {
  27. return false
  28. }
  29. auth, exists = session.Values["authenticated"].(bool)
  30. if !(auth && exists) {
  31. return false
  32. }
  33. lastLoginUnix, exists = session.Values["lastLogin"].(int64)
  34. if !exists {
  35. return false
  36. }
  37. lastLogin = time.Unix(lastLoginUnix, 0)
  38. lastLogin = lastLogin.Add(3 * time.Hour)
  39. if time.Now().After(lastLogin) {
  40. session.Values = make(map[interface{}]interface{})
  41. session.Values["authenticated"] = false
  42. session.AddFlash("Login Expired")
  43. e = session.Save(r, w)
  44. if e != nil {
  45. log.Println(e.Error())
  46. }
  47. return false
  48. }
  49. return true
  50. }
  51. func AdminView(w http.ResponseWriter, r *http.Request) {
  52. var (
  53. v = make(map[string]interface{})
  54. urlParams map[string]string
  55. page string
  56. pageInt int
  57. pageOffset int
  58. posts []database.Post
  59. exists bool
  60. e error
  61. )
  62. if !CheckAuth(w, r) {
  63. http.Redirect(w, r, "/admin/login", 302)
  64. return
  65. }
  66. switch r.Method {
  67. case http.MethodGet:
  68. urlParams = mux.Vars(r)
  69. page, exists = urlParams["page"]
  70. if exists {
  71. pageInt, e = strconv.Atoi(page)
  72. if e != nil {
  73. log.Fatal("Url Parameter page cannot be converted to an int")
  74. }
  75. } else {
  76. pageInt = 0
  77. }
  78. pageOffset = pageInt * 10
  79. posts, e = database.GetPostsList(10, pageOffset)
  80. v["Posts"] = posts
  81. ServeTemplate(w, r, "html/admin/admin-index.gohtml", v)
  82. return
  83. }
  84. }
  85. func comparePasswords(hashedPwd, plainPwd string) bool {
  86. var (
  87. e error
  88. )
  89. e = bcrypt.CompareHashAndPassword(
  90. []byte(hashedPwd),
  91. []byte(plainPwd),
  92. )
  93. if e != nil {
  94. return false
  95. }
  96. return true
  97. }
  98. func AdminLogout(w http.ResponseWriter, r *http.Request) {
  99. var (
  100. session *sessions.Session
  101. e error
  102. )
  103. if !CheckAuth(w, r) {
  104. http.Redirect(w, r, "/admin/login", 302)
  105. return
  106. }
  107. session, e = variables.CookieStore.Get(r, variables.CookieName)
  108. if e != nil {
  109. log.Println("Could not get session cookie")
  110. http.Error(w, "Error", http.StatusInternalServerError)
  111. return
  112. }
  113. session.Values["authenticated"] = false
  114. session.Values["lastLogin"] = nil
  115. session.Save(r, w)
  116. http.Redirect(w, r, "/admin/logout", 302)
  117. return
  118. }
  119. func AdminLogin(w http.ResponseWriter, r *http.Request) {
  120. var (
  121. session *sessions.Session
  122. v = make(map[string]interface{})
  123. flashes []interface{}
  124. username string
  125. password string
  126. e error
  127. )
  128. if CheckAuth(w, r) {
  129. http.Redirect(w, r, "/admin", 302)
  130. return
  131. }
  132. session, e = variables.CookieStore.Get(r, variables.CookieName)
  133. if e != nil {
  134. log.Println("Could not get session cookie")
  135. http.Error(w, "Error", http.StatusInternalServerError)
  136. return
  137. }
  138. switch r.Method {
  139. case http.MethodGet:
  140. flashes = session.Flashes()
  141. e = session.Save(r, w)
  142. if e != nil {
  143. log.Println(e.Error())
  144. return
  145. }
  146. if len(flashes) > 0 {
  147. v["FlashMsg"] = flashes[0].(string)
  148. }
  149. ServeTemplate(w, r, "html/admin/admin-login.gohtml", v)
  150. return
  151. case http.MethodPost:
  152. e = r.ParseForm()
  153. if e != nil {
  154. log.Println(e.Error())
  155. http.Redirect(w, r, "/login", 302)
  156. }
  157. username = r.FormValue("username")
  158. password = r.FormValue("password")
  159. if username != variables.AdminPassword && !comparePasswords(variables.AdminPassword, password) {
  160. session.AddFlash("Invalid Username or Password")
  161. e = session.Save(r, w)
  162. if e != nil {
  163. log.Println(e.Error())
  164. }
  165. http.Redirect(w, r, "/admin/login", 302)
  166. return
  167. }
  168. session.Values["authenticated"] = true
  169. session.Values["lastLogin"] = time.Now().Unix()
  170. session.Save(r, w)
  171. http.Redirect(w, r, "/admin", 302)
  172. return
  173. }
  174. }
  175. func AdminNewPost(w http.ResponseWriter, r *http.Request) {
  176. var (
  177. session *sessions.Session
  178. v = make(map[string]interface{})
  179. flashes []interface{}
  180. title, subject, intro, body string
  181. bodyPath string
  182. mainFilePath string = ""
  183. fileUpload []*multipart.FileHeader
  184. //otherImgs string
  185. e error
  186. )
  187. if !CheckAuth(w, r) {
  188. http.Redirect(w, r, "/admin/login", 302)
  189. return
  190. }
  191. session, e = variables.CookieStore.Get(r, variables.CookieName)
  192. if e != nil {
  193. log.Println("Could not get session cookie")
  194. http.Error(w, "Error", http.StatusInternalServerError)
  195. return
  196. }
  197. switch r.Method {
  198. case http.MethodGet:
  199. flashes = session.Flashes()
  200. e = session.Save(r, w)
  201. if e != nil {
  202. log.Println(e.Error())
  203. return
  204. }
  205. if len(flashes) > 0 {
  206. v["FlashMsg"] = flashes[0].(string)
  207. }
  208. ServeTemplate(w, r, "html/admin/admin-new-post.gohtml", v)
  209. return
  210. case http.MethodPost:
  211. title = r.FormValue("title")
  212. subject = r.FormValue("subject")
  213. intro = r.FormValue("intro")
  214. body = r.FormValue("body")
  215. bodyPath, e = helper.WriteBody(title, body)
  216. if e != nil {
  217. log.Fatal(e)
  218. }
  219. r.ParseMultipartForm(32 << 20) // 32MB is the default used by FormFile
  220. fileUpload = r.MultipartForm.File["img"]
  221. helper.UploadFiles(fileUpload)
  222. if len(fileUpload) == 1 {
  223. mainFilePath = fileUpload[0].Filename
  224. }
  225. fileUpload = r.MultipartForm.File["files"]
  226. helper.UploadFiles(fileUpload)
  227. database.CreatePost(
  228. database.Post{
  229. Title: title,
  230. Subject: subject,
  231. Intro: intro,
  232. HtmlPath: bodyPath,
  233. MainImage: mainFilePath,
  234. },
  235. )
  236. http.Redirect(w, r, "/admin", 302)
  237. return
  238. }
  239. }
  240. func AdminEditPost(w http.ResponseWriter, r *http.Request) {
  241. var (
  242. session *sessions.Session
  243. v = make(map[string]interface{})
  244. urlParams map[string]string
  245. flashes []interface{}
  246. title, subject, intro, body string
  247. bodyPath string
  248. post database.Post
  249. fileUpload []*multipart.FileHeader
  250. e error
  251. )
  252. if !CheckAuth(w, r) {
  253. http.Redirect(w, r, "/admin/login", 302)
  254. return
  255. }
  256. session, e = variables.CookieStore.Get(r, variables.CookieName)
  257. if e != nil {
  258. log.Println("Could not get session cookie")
  259. http.Error(w, "Error", http.StatusInternalServerError)
  260. return
  261. }
  262. switch r.Method {
  263. case http.MethodGet:
  264. flashes = session.Flashes()
  265. e = session.Save(r, w)
  266. if e != nil {
  267. log.Println(e.Error())
  268. return
  269. }
  270. if len(flashes) > 0 {
  271. v["FlashMsg"] = flashes[0].(string)
  272. }
  273. urlParams = mux.Vars(r)
  274. post, e = database.GetPostById(urlParams["id"])
  275. if e != nil {
  276. log.Fatal("Cannot get Post by id")
  277. }
  278. post.Body, e = helper.GetFileContents(post.HtmlPath)
  279. if e != nil {
  280. log.Fatal("Cannot read body file")
  281. }
  282. v["Post"] = post
  283. ServeTemplate(w, r, "html/admin/admin-update-post.gohtml", v)
  284. return
  285. case http.MethodPost:
  286. urlParams = mux.Vars(r)
  287. post, e = database.GetPostById(urlParams["id"])
  288. if e != nil {
  289. log.Fatal("Cannot get Post by id")
  290. }
  291. title = r.FormValue("title")
  292. subject = r.FormValue("subject")
  293. intro = r.FormValue("intro")
  294. body = r.FormValue("body")
  295. if title != post.Title {
  296. defer helper.DeleteOldPostFile(post.Title)
  297. }
  298. bodyPath, e = helper.WriteBody(title, body)
  299. if e != nil {
  300. log.Fatal(e)
  301. }
  302. r.ParseMultipartForm(32 << 20) // 32MB is the default used by FormFile
  303. fileUpload = r.MultipartForm.File["img"]
  304. helper.UploadFiles(fileUpload)
  305. if len(fileUpload) == 1 {
  306. post.MainImage = fileUpload[0].Filename
  307. }
  308. fileUpload = r.MultipartForm.File["files"]
  309. helper.UploadFiles(fileUpload)
  310. post.Title = title
  311. post.Subject = subject
  312. post.Intro = intro
  313. post.HtmlPath = bodyPath
  314. database.UpdatePost(
  315. post,
  316. )
  317. http.Redirect(w, r, fmt.Sprintf("/admin/post/%s/edit", post.ID), 302)
  318. return
  319. }
  320. }