router.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. package main
  2. import (
  3. "notabug.org/apiote/amuse/accounts"
  4. "notabug.org/apiote/amuse/db"
  5. "notabug.org/apiote/amuse/front"
  6. "notabug.org/apiote/amuse/libamuse"
  7. "notabug.org/apiote/amuse/network"
  8. "notabug.org/apiote/amuse/config"
  9. "crypto/sha256"
  10. "encoding/base64"
  11. "errors"
  12. "fmt"
  13. "io"
  14. "mime"
  15. "net/http"
  16. "net/url"
  17. "os"
  18. "strconv"
  19. "strings"
  20. "time"
  21. )
  22. func person(w http.ResponseWriter, r *http.Request) {
  23. acceptLanguages := r.Header.Get("Accept-Language")
  24. etag := r.Header.Get("Etag")
  25. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  26. auth := getAuthToken(r)
  27. defer recovery(acceptLanguages, mimetype, w)
  28. path := strings.Split(r.URL.Path[1:], "/")
  29. _, err := strconv.ParseInt(path[1], 10, 64)
  30. if err != nil {
  31. renderError(400, w, err, acceptLanguages, mimetype)
  32. return
  33. } else if len(path) > 2 {
  34. renderError(404, w, nil, acceptLanguages, mimetype)
  35. return
  36. }
  37. person, err := libamuse.ShowPerson(path[1], etag, acceptLanguages, mimetype, auth)
  38. render(person, err, w, acceptLanguages, mimetype)
  39. }
  40. func tvSerie(w http.ResponseWriter, r *http.Request) {
  41. acceptLanguages := r.Header.Get("Accept-Language")
  42. etag := r.Header.Get("Etag")
  43. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  44. auth := getAuthToken(r)
  45. defer recovery(acceptLanguages, mimetype, w)
  46. path := strings.Split(r.URL.Path[1:], "/")
  47. _, err := strconv.ParseInt(path[1], 10, 64)
  48. if err != nil {
  49. renderError(400, w, err, acceptLanguages, mimetype)
  50. return
  51. } else if len(path) > 2 {
  52. renderError(404, w, nil, acceptLanguages, mimetype)
  53. return
  54. }
  55. tvSerie, err := libamuse.ShowTvSerie(path[1], etag, acceptLanguages, mimetype, auth)
  56. render(tvSerie, err, w, acceptLanguages, mimetype)
  57. }
  58. func film(w http.ResponseWriter, r *http.Request) {
  59. acceptLanguages := r.Header.Get("Accept-Language")
  60. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  61. auth := getAuthToken(r)
  62. defer recovery(acceptLanguages, mimetype, w)
  63. path := strings.Split(r.URL.Path[1:], "/")
  64. _, err := strconv.ParseInt(path[1], 10, 64)
  65. if err != nil {
  66. renderError(400, w, err, acceptLanguages, mimetype)
  67. return
  68. } else if len(path) > 2 {
  69. renderError(404, w, nil, acceptLanguages, mimetype)
  70. return
  71. }
  72. film, err := libamuse.ShowFilm(path[1], acceptLanguages, mimetype, auth)
  73. render(film, err, w, acceptLanguages, mimetype)
  74. }
  75. func book(w http.ResponseWriter, r *http.Request) {
  76. acceptLanguages := r.Header.Get("Accept-Language")
  77. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  78. auth := getAuthToken(r)
  79. defer recovery(acceptLanguages, mimetype, w)
  80. path := strings.Split(r.URL.Path[1:], "/")
  81. if len(path) > 2 {
  82. renderError(404, w, nil, acceptLanguages, mimetype)
  83. return
  84. }
  85. book, err := libamuse.ShowBook(path[1], acceptLanguages, mimetype, auth)
  86. render(book, err, w, acceptLanguages, mimetype)
  87. }
  88. func bookSerie(w http.ResponseWriter, r *http.Request) {
  89. acceptLanguages := r.Header.Get("Accept-Language")
  90. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  91. auth := getAuthToken(r)
  92. defer recovery(acceptLanguages, mimetype, w)
  93. path := strings.Split(r.URL.Path[1:], "/")
  94. if len(path) > 2 {
  95. renderError(404, w, nil, acceptLanguages, mimetype)
  96. return
  97. }
  98. bookSerie, err := libamuse.ShowBookSerie(path[1], acceptLanguages, mimetype, auth)
  99. render(bookSerie, err, w, acceptLanguages, mimetype)
  100. }
  101. func search(w http.ResponseWriter, r *http.Request) {
  102. acceptLanguages := r.Header.Get("Accept-Language")
  103. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  104. auth := getAuthToken(r)
  105. defer recovery(acceptLanguages, mimetype, w)
  106. path := strings.Split(r.URL.Path[1:], "/")
  107. if len(path) > 2 {
  108. renderError(404, w, nil, acceptLanguages, mimetype)
  109. return
  110. }
  111. query := r.URL.Query().Get("q")
  112. page := r.URL.Query().Get("page")
  113. results, err := libamuse.PerformSearch(query, acceptLanguages, mimetype, page, auth)
  114. render(results, err, w, acceptLanguages, mimetype)
  115. }
  116. func index(w http.ResponseWriter, r *http.Request) {
  117. acceptLanguages := r.Header.Get("Accept-Language")
  118. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  119. auth := getAuthToken(r)
  120. defer recovery(acceptLanguages, mimetype, w)
  121. path := strings.Split(r.URL.Path[1:], "/")
  122. if path[0] != "" {
  123. renderError(404, w, nil, acceptLanguages, mimetype)
  124. return
  125. }
  126. index, err := libamuse.ShowIndex(acceptLanguages, mimetype, auth)
  127. render(index, err, w, acceptLanguages, mimetype)
  128. }
  129. func about(w http.ResponseWriter, r *http.Request) {
  130. acceptLanguages := r.Header.Get("Accept-Language")
  131. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  132. auth := getAuthToken(r)
  133. defer recovery(acceptLanguages, mimetype, w)
  134. about, err := libamuse.ShowAbout(acceptLanguages, mimetype, auth)
  135. render(about, err, w, acceptLanguages, mimetype)
  136. }
  137. func loginGet(w http.ResponseWriter, r *http.Request, acceptLanguages, mimetype string) {
  138. referer := r.Header.Get("Referer")
  139. target := getTarget(referer, r.Host)
  140. if target == "/signedup" {
  141. target = "/"
  142. }
  143. auth := getAuthToken(r)
  144. user, _ := libamuse.VerifyAuthToken(auth)
  145. if !user.IsEmpty() {
  146. w.Header().Add("Location", target)
  147. w.WriteHeader(303)
  148. return
  149. }
  150. login, err := libamuse.ShowLogin(acceptLanguages, mimetype, nil, target)
  151. render(login, err, w, acceptLanguages, mimetype)
  152. }
  153. func loginPost(w http.ResponseWriter, r *http.Request, acceptLanguages, mimetype string) {
  154. // todo check mimetype (html,capnproto)
  155. r.ParseForm()
  156. username := r.PostForm.Get("username")
  157. password := r.PostForm.Get("password")
  158. target := r.PostForm.Get("target")
  159. if target == "" {
  160. target = "/"
  161. }
  162. sfa := r.PostForm.Get("sfa")
  163. remember := r.PostForm.Get("remember") == "true"
  164. token, err := libamuse.DoLogin(username, password, sfa, remember)
  165. if err != nil {
  166. fmt.Println(err)
  167. if authErr, ok := err.(accounts.AuthError); ok {
  168. var login string
  169. var err error
  170. if mimetype == "text/html" {
  171. login, err = libamuse.ShowLogin(acceptLanguages, mimetype, &authErr, target)
  172. } else {
  173. // todo send capnproto not authed
  174. }
  175. render(login, err, w, acceptLanguages, mimetype)
  176. } else {
  177. render("", err, w, acceptLanguages, mimetype)
  178. }
  179. } else {
  180. if mimetype == "text/html" {
  181. setAuthCookie(remember, token, w)
  182. w.Header().Add("Location", target)
  183. w.WriteHeader(303)
  184. } else {
  185. // todo send capnproto authed
  186. }
  187. }
  188. }
  189. func login(w http.ResponseWriter, r *http.Request) {
  190. acceptLanguages := r.Header.Get("Accept-Language")
  191. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  192. defer recovery(acceptLanguages, mimetype, w)
  193. if r.Method == "" || r.Method == "GET" {
  194. loginGet(w, r, acceptLanguages, mimetype)
  195. } else if r.Method == "POST" {
  196. loginPost(w, r, acceptLanguages, mimetype)
  197. }
  198. }
  199. func signupGet(w http.ResponseWriter, r *http.Request, acceptLanguages, mimetype string) {
  200. auth := getAuthToken(r)
  201. user, _ := libamuse.VerifyAuthToken(auth)
  202. host := r.Host
  203. if !user.IsEmpty() {
  204. w.Header().Add("Location", "/")
  205. w.WriteHeader(303)
  206. return
  207. }
  208. signup, err := libamuse.ShowSignup(acceptLanguages, mimetype, nil, false, "", "", host)
  209. render(signup, err, w, acceptLanguages, mimetype)
  210. }
  211. func signupPost(w http.ResponseWriter, r *http.Request, acceptLanguages, mimetype string) {
  212. // todo check mimetype (html,capnproto)
  213. if !config.OpenRegistration {
  214. err := errors.New("423")
  215. render("", err, w, acceptLanguages, mimetype)
  216. return
  217. }
  218. r.ParseForm()
  219. username := r.PostForm.Get("username")
  220. password := r.PostForm.Get("password")
  221. passwordConfirm := r.PostForm.Get("password2")
  222. sfaEnabled := r.PostForm.Get("sfaEnabled") == "true"
  223. sfaSecret := r.PostForm.Get("sfaSecret")
  224. sfa := r.PostForm.Get("sfa")
  225. host := r.Host
  226. recoveryCodes, err := libamuse.DoSignup(username, password, passwordConfirm, sfaEnabled, sfaSecret, sfa)
  227. if err != nil {
  228. fmt.Println(err)
  229. if authErr, ok := err.(accounts.AuthError); ok {
  230. var signup string
  231. var err error
  232. if mimetype == "text/html" {
  233. signup, err = libamuse.ShowSignup(acceptLanguages, mimetype, &authErr, sfaEnabled, sfaSecret, username, host)
  234. } else {
  235. // todo send capnproto not authed
  236. }
  237. render(signup, err, w, acceptLanguages, mimetype)
  238. } else {
  239. render("", err, w, acceptLanguages, mimetype)
  240. }
  241. } else {
  242. if mimetype == "text/html" {
  243. w.Header().Add("Location", "/signedup?recoveryCodes="+recoveryCodes)
  244. w.WriteHeader(303)
  245. } else {
  246. // todo send capnproto authed
  247. }
  248. }
  249. }
  250. func signup(w http.ResponseWriter, r *http.Request) {
  251. acceptLanguages := r.Header.Get("Accept-Language")
  252. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  253. defer recovery(acceptLanguages, mimetype, w)
  254. if r.Method == "" || r.Method == "GET" {
  255. signupGet(w, r, acceptLanguages, mimetype)
  256. } else if r.Method == "POST" {
  257. signupPost(w, r, acceptLanguages, mimetype)
  258. }
  259. }
  260. func signedup(w http.ResponseWriter, r *http.Request) {
  261. acceptLanguages := r.Header.Get("Accept-Language")
  262. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  263. recoveryCodes := r.URL.Query().Get("recoveryCodes")
  264. defer recovery(acceptLanguages, mimetype, w)
  265. signedup, err := libamuse.ShowSignedup(acceptLanguages, mimetype, recoveryCodes)
  266. render(signedup, err, w, acceptLanguages, mimetype)
  267. }
  268. func static(w http.ResponseWriter, r *http.Request) {
  269. etagReq := r.Header.Get("If-None-Match")
  270. f, err := os.Open(config.DataHome + "/" + r.URL.Path[1:])
  271. if err != nil {
  272. w.WriteHeader(500)
  273. return
  274. }
  275. defer f.Close()
  276. h := sha256.New()
  277. if _, err := io.Copy(h, f); err != nil {
  278. w.WriteHeader(500)
  279. return
  280. }
  281. etag := base64.StdEncoding.EncodeToString(h.Sum(nil))
  282. mime.AddExtensionType(".woff2", "font/woff2")
  283. w.Header().Set("ETag", etag)
  284. if etagReq == etag {
  285. w.WriteHeader(304)
  286. } else {
  287. s := strings.Split(f.Name(), ".")
  288. ext := "." + s[len(s)-1]
  289. mimetype := mime.TypeByExtension(ext)
  290. w.Header().Set("Content-Type", mimetype+"; charset=utf-8")
  291. f.Seek(0, 0)
  292. if _, err := io.Copy(w, f); err != nil {
  293. w.WriteHeader(500)
  294. }
  295. }
  296. }
  297. func user(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages, mimetype string) {
  298. // todo user profile
  299. renderError(404, w, nil, acceptLanguages, mimetype)
  300. }
  301. func userAvatar(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages string, mimetype string) {
  302. etagReq := r.Header.Get("If-None-Match")
  303. r.ParseForm()
  304. size := r.Form.Get("size")
  305. avatar, err := libamuse.ShowUserAvatar(username, etagReq, auth, size == "small")
  306. if err != nil {
  307. render("", err, w, acceptLanguages, mimetype)
  308. }
  309. if string(avatar.Data) == "" {
  310. w.WriteHeader(304)
  311. return
  312. }
  313. w.Header().Set("Content-Type", avatar.Mimetype)
  314. w.Header().Set("ETag", avatar.Etag)
  315. w.Write(avatar.Data)
  316. }
  317. func addToWantlist(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages, mimetype string) {
  318. r.ParseForm()
  319. itemId := r.PostForm.Get("itemId")
  320. itemType := r.PostForm.Get("itemType")
  321. target := "/" + itemType + "s/" + itemId
  322. err := libamuse.AddToWantlist(username, auth, itemId, itemType, acceptLanguages, mimetype)
  323. if err != nil {
  324. render("", err, w, acceptLanguages, mimetype)
  325. } else {
  326. w.Header().Add("Location", target)
  327. w.WriteHeader(303)
  328. }
  329. }
  330. func userWatchlist(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages string, mimetype string) {
  331. if r.Method == "" || r.Method == "GET" {
  332. var page int
  333. r.ParseForm()
  334. filter := r.Form.Get("filter")
  335. fmt.Sscanf(r.Form.Get("page"), "%d", &page)
  336. watchlist, err := libamuse.ShowWatchlist(username, auth, acceptLanguages, mimetype, filter, page)
  337. render(watchlist, err, w, acceptLanguages, mimetype)
  338. } else if r.Method == "POST" {
  339. addToWantlist(w, r, username, auth, acceptLanguages, mimetype)
  340. }
  341. }
  342. func userTvQueue(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages string, mimetype string) {
  343. if r.Method == "" || r.Method == "GET" {
  344. var page int
  345. r.ParseForm()
  346. filter := r.Form.Get("filter")
  347. fmt.Sscanf(r.Form.Get("page"), "%d", &page)
  348. tvQueue, err := libamuse.ShowTvQueue(username, auth, acceptLanguages, mimetype, filter, page)
  349. render(tvQueue, err, w, acceptLanguages, mimetype)
  350. } else if r.Method == "POST" {
  351. r.ParseForm()
  352. itemId := r.PostForm.Get("itemId")
  353. itemType := r.PostForm.Get("itemType")
  354. masterItemId := strings.Split(itemId, "/")[0]
  355. target := "/" + itemType + "s/" + masterItemId
  356. err := libamuse.AddToWantlist(username, auth, itemId, itemType, acceptLanguages, mimetype)
  357. if err != nil {
  358. render("", err, w, acceptLanguages, mimetype)
  359. } else {
  360. w.Header().Add("Location", target)
  361. w.WriteHeader(303)
  362. }
  363. }
  364. }
  365. func userReadlist(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages string, mimetype string) {
  366. if r.Method == "" || r.Method == "GET" {
  367. var page int
  368. r.ParseForm()
  369. filter := r.Form.Get("filter")
  370. fmt.Sscanf(r.Form.Get("page"), "%d", &page)
  371. readlist, err := libamuse.ShowReadlist(username, auth, acceptLanguages, mimetype, filter, page)
  372. render(readlist, err, w, acceptLanguages, mimetype)
  373. } else if r.Method == "POST" {
  374. addToWantlist(w, r, username, auth, acceptLanguages, mimetype)
  375. }
  376. }
  377. func userExperiences(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages string, mimetype string) {
  378. if r.Method == "" || r.Method == "GET" {
  379. var page int
  380. r.ParseForm()
  381. filter := r.Form.Get("filter")
  382. fmt.Sscanf(r.Form.Get("page"), "%d", &page)
  383. experiences, err := libamuse.ShowExperiences(username, auth, acceptLanguages, mimetype, filter, page)
  384. render(experiences, err, w, acceptLanguages, mimetype)
  385. } else if r.Method == "POST" {
  386. r.ParseForm()
  387. itemId := r.PostForm.Get("itemId")
  388. itemType := r.PostForm.Get("itemType")
  389. isOtherTime := r.PostForm.Get("isOtherTime") == "true"
  390. var datetime string
  391. if isOtherTime {
  392. date := r.PostForm.Get("experiencedDate")
  393. time := r.PostForm.Get("experiencedTime")
  394. datetime = date + "T" + time + ":00"
  395. } else {
  396. datetime = ""
  397. }
  398. masterItemId := strings.Split(itemId, "/")[0]
  399. target := "/" + itemType + "s/" + masterItemId
  400. err := libamuse.AddToExperiences(username, auth, itemId, itemType, datetime, acceptLanguages, mimetype)
  401. if err != nil {
  402. render("", err, w, acceptLanguages, mimetype)
  403. } else {
  404. w.Header().Add("Location", target)
  405. w.WriteHeader(303)
  406. }
  407. }
  408. }
  409. func sessionDelete(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, session, acceptLanguages, mimetype string) {
  410. err := libamuse.SessionDelete(username, auth, session, acceptLanguages, mimetype)
  411. if err != nil {
  412. render("", err, w, acceptLanguages, mimetype)
  413. } else {
  414. w.Header().Add("Location", "/loggedout")
  415. w.WriteHeader(303)
  416. }
  417. }
  418. func userSessions(w http.ResponseWriter, r *http.Request, username string, auth accounts.Authentication, acceptLanguages, mimetype string) {
  419. path := strings.Split(r.URL.Path[1:], "/")
  420. if len(path) == 3 {
  421. // todo show sessions
  422. renderError(404, w, nil, acceptLanguages, mimetype)
  423. } else if len(path) == 4 {
  424. if r.Method == "POST" {
  425. r.ParseForm()
  426. method := r.PostForm.Get("method")
  427. session := path[3]
  428. if method == "DELETE" {
  429. sessionDelete(w, r, username, auth, session, acceptLanguages, mimetype)
  430. }
  431. } else if r.Method == "DELETE" {
  432. session := path[3]
  433. sessionDelete(w, r, username, auth, session, acceptLanguages, mimetype)
  434. }
  435. }
  436. }
  437. func userRouter(w http.ResponseWriter, r *http.Request) {
  438. path := strings.Split(r.URL.Path[1:], "/")
  439. acceptLanguages := r.Header.Get("Accept-Language")
  440. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  441. auth := getAuthToken(r)
  442. defer recovery(acceptLanguages, mimetype, w)
  443. if path[1] == "" {
  444. renderError(404, w, nil, acceptLanguages, mimetype)
  445. return
  446. }
  447. username := path[1]
  448. if len(path) == 2 {
  449. user(w, r, username, auth, acceptLanguages, mimetype)
  450. } else {
  451. switch path[2] {
  452. case "avatar":
  453. userAvatar(w, r, username, auth, acceptLanguages, mimetype)
  454. case "watchlist":
  455. userWatchlist(w, r, username, auth, acceptLanguages, mimetype)
  456. case "tvqueue":
  457. userTvQueue(w, r, username, auth, acceptLanguages, mimetype)
  458. case "readlist":
  459. userReadlist(w, r, username, auth, acceptLanguages, mimetype)
  460. case "experiences":
  461. userExperiences(w, r, username, auth, acceptLanguages, mimetype)
  462. case "sessions":
  463. userSessions(w, r, username, auth, acceptLanguages, mimetype)
  464. default:
  465. renderError(404, w, nil, acceptLanguages, mimetype)
  466. }
  467. }
  468. }
  469. func loggedout(w http.ResponseWriter, r *http.Request) {
  470. acceptLanguages := r.Header.Get("Accept-Language")
  471. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  472. defer recovery(acceptLanguages, mimetype, w)
  473. loggedout, err := libamuse.ShowLoggedOut(acceptLanguages, mimetype)
  474. setAuthCookie(false, "", w)
  475. render(loggedout, err, w, acceptLanguages, mimetype)
  476. }
  477. func route(port uint) {
  478. address := fmt.Sprintf("%s:%d", config.Address, port)
  479. http.HandleFunc("/", index)
  480. http.HandleFunc("/static/", static)
  481. http.HandleFunc("/about", about)
  482. http.HandleFunc("/items/", search)
  483. http.HandleFunc("/films/", film)
  484. http.HandleFunc("/tvseries/", tvSerie)
  485. http.HandleFunc("/persons/", person)
  486. http.HandleFunc("/books/", book)
  487. http.HandleFunc("/bookseries/", bookSerie)
  488. http.HandleFunc("/users/", userRouter)
  489. http.HandleFunc("/login", login)
  490. http.HandleFunc("/signup", signup)
  491. http.HandleFunc("/signedup", signedup)
  492. http.HandleFunc("/loggedout", loggedout)
  493. fmt.Printf("running on %s\n", address)
  494. e := http.ListenAndServe(address, nil)
  495. if e != nil {
  496. fmt.Println(e)
  497. }
  498. }
  499. func getTarget(referer, host string) string {
  500. url, err := url.Parse(referer)
  501. if err != nil {
  502. fmt.Println(err)
  503. return "/"
  504. }
  505. target := url.EscapedPath()
  506. if target == "" || url.Host != host {
  507. target = "/"
  508. }
  509. return target
  510. }
  511. func setAuthCookie(remember bool, token string, w http.ResponseWriter) {
  512. cookie := http.Cookie{
  513. Name: "auth", Value: token, HttpOnly: true,
  514. //SameSite: http.SameSiteStrictMode, Secure: true, // note turn on in prod (https)
  515. }
  516. if remember {
  517. cookie.Expires = time.Now().Add(1000000000 * 60 * 60 * 24 * 30)
  518. } else {
  519. cookie.Expires = time.Now().Add(1000000000 * 60 * 60 * 24)
  520. }
  521. http.SetCookie(w, &cookie)
  522. }
  523. func getAuthToken(r *http.Request) accounts.Authentication {
  524. cookie, err := r.Cookie("auth")
  525. if err == nil {
  526. return accounts.Authentication{
  527. Token: cookie.Value,
  528. }
  529. }
  530. return accounts.Authentication{
  531. Token: r.Header.Get("Authorization"),
  532. }
  533. }
  534. func recovery(languages, mimetype string, w http.ResponseWriter) {
  535. if r := recover(); r != nil {
  536. renderError(500, w, errors.New(r.(string)), languages, mimetype)
  537. }
  538. }
  539. func render(result string, e error, w http.ResponseWriter, languages, mimetype string) {
  540. if e != nil {
  541. fmt.Println(e)
  542. if _, ok := e.(front.NoSuchRendererError); ok {
  543. renderError(406, w, e, languages, mimetype)
  544. } else if httpError, ok := e.(network.HttpError); ok {
  545. renderError(httpError.Status, w, httpError, languages, mimetype)
  546. } else if _, ok := e.(db.EmptyError); ok {
  547. renderError(410, w, e, languages, mimetype)
  548. } else if authError, ok := e.(accounts.AuthError); ok {
  549. if authError.Err.Error() == "401" {
  550. w.Header().Add("WWW-Authenticate", "Bearer")
  551. renderError(401, w, e, languages, mimetype)
  552. } else {
  553. renderError(403, w, e, languages, mimetype)
  554. }
  555. } else if e.Error() == "423" {
  556. renderError(423, w, e, languages, mimetype)
  557. } else {
  558. renderError(500, w, e, languages, mimetype)
  559. }
  560. } else {
  561. fmt.Fprint(w, result)
  562. }
  563. }
  564. func renderError(code int, w http.ResponseWriter, e error, languages, mimetype string) {
  565. w.WriteHeader(code)
  566. if code != 406 {
  567. errorPage, err := libamuse.ShowErrorPage(code, languages, mimetype)
  568. if err != nil {
  569. fmt.Fprintf(w, "Fatal error while rendering error %d.\nContact admin.", code)
  570. }
  571. fmt.Fprint(w, errorPage)
  572. }
  573. }