From c3d90539e9a7addd3c41f44b864b14bde60958dc Mon Sep 17 00:00:00 2001 From: r Date: Sat, 14 Nov 2020 14:08:16 +0000 Subject: Add notification interval setting It replaces the "Auto refresh notifications" checkbox --- service/transport.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'service/transport.go') diff --git a/service/transport.go b/service/transport.go index 6c0975d..3c9392a 100644 --- a/service/transport.go +++ b/service/transport.go @@ -589,22 +589,22 @@ func NewHandler(s Service, staticDir string) http.Handler { threadInNewTab := req.FormValue("thread_in_new_tab") == "true" hideAttachments := req.FormValue("hide_attachments") == "true" maskNSFW := req.FormValue("mask_nsfw") == "true" - arn := req.FormValue("auto_refresh_notifications") == "true" + ni, _ := strconv.Atoi(req.FormValue("notification_interval")) fluorideMode := req.FormValue("fluoride_mode") == "true" darkMode := req.FormValue("dark_mode") == "true" antiDopamineMode := req.FormValue("anti_dopamine_mode") == "true" settings := &model.Settings{ - DefaultVisibility: visibility, - DefaultFormat: format, - CopyScope: copyScope, - ThreadInNewTab: threadInNewTab, - HideAttachments: hideAttachments, - MaskNSFW: maskNSFW, - AutoRefreshNotifications: arn, - FluorideMode: fluorideMode, - DarkMode: darkMode, - AntiDopamineMode: antiDopamineMode, + DefaultVisibility: visibility, + DefaultFormat: format, + CopyScope: copyScope, + ThreadInNewTab: threadInNewTab, + HideAttachments: hideAttachments, + MaskNSFW: maskNSFW, + NotificationInterval: ni, + FluorideMode: fluorideMode, + DarkMode: darkMode, + AntiDopamineMode: antiDopamineMode, } err := s.SaveSettings(c, settings) -- cgit v1.2.3 From fa27d9c6eb525b2e55c3faab5dd8a3e0e9658536 Mon Sep 17 00:00:00 2001 From: r Date: Sun, 22 Nov 2020 17:29:58 +0000 Subject: Refactor things - Remove separate auth/logging and merge them into transport.go - Add helper function for http handlers --- service/transport.go | 1026 +++++++++++++++++++++----------------------------- 1 file changed, 419 insertions(+), 607 deletions(-) (limited to 'service/transport.go') diff --git a/service/transport.go b/service/transport.go index 3c9392a..80ad7f1 100644 --- a/service/transport.go +++ b/service/transport.go @@ -2,597 +2,478 @@ package service import ( "encoding/json" - "io" - "mime/multipart" + "errors" + "log" "net/http" "strconv" "time" + "bloat/mastodon" "bloat/model" "github.com/gorilla/mux" ) +var ( + errInvalidSession = errors.New("invalid session") + errInvalidCSRFToken = errors.New("invalid csrf token") +) + const ( sessionExp = 365 * 24 * time.Hour ) -func newClient(w io.Writer, req *http.Request, csrfToken string) *model.Client { - var sessionID string - if req != nil { - c, err := req.Cookie("session_id") - if err == nil { - sessionID = c.Value - } - } - return &model.Client{ - Writer: w, - Ctx: model.ClientCtx{ - SessionID: sessionID, - CSRFToken: csrfToken, - }, - } +type respType int + +const ( + HTML respType = iota + JSON +) + +type authType int + +const ( + NOAUTH authType = iota + SESSION + CSRF +) + +type client struct { + *mastodon.Client + http.ResponseWriter + Req *http.Request + CSRFToken string + Session model.Session } -func setSessionCookie(w http.ResponseWriter, sessionID string, exp time.Duration) { +func setSessionCookie(w http.ResponseWriter, sid string, exp time.Duration) { http.SetCookie(w, &http.Cookie{ Name: "session_id", - Value: sessionID, + Value: sid, Expires: time.Now().Add(exp), }) } -func getMultipartFormValue(mf *multipart.Form, key string) (val string) { - vals, ok := mf.Value[key] - if !ok { - return "" - } - if len(vals) < 1 { - return "" - } - return vals[0] -} - -func serveJson(w io.Writer, data interface{}) (err error) { - var d = make(map[string]interface{}) - d["data"] = data - return json.NewEncoder(w).Encode(d) +func writeJson(c *client, data interface{}) error { + return json.NewEncoder(c).Encode(map[string]interface{}{ + "data": data, + }) } -func serveJsonError(w http.ResponseWriter, err error) { - var d = make(map[string]interface{}) - d["error"] = err.Error() - w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(d) - return +func redirect(c *client, url string) { + c.Header().Add("Location", url) + c.WriteHeader(http.StatusFound) } -func NewHandler(s Service, staticDir string) http.Handler { +func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { r := mux.NewRouter() - rootPage := func(w http.ResponseWriter, req *http.Request) { - sessionID, _ := req.Cookie("session_id") - if sessionID != nil && len(sessionID.Value) > 0 { - c := newClient(w, req, "") - err := s.ServeRootPage(c) - if err != nil { - if err == errInvalidAccessToken { - w.Header().Add("Location", "/signin") - w.WriteHeader(http.StatusFound) - return - } - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } else { - w.Header().Add("Location", "/signin") - w.WriteHeader(http.StatusFound) - } - } - - navPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - err := s.ServeNavPage(c) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + writeError := func(c *client, err error, t respType) { + switch t { + case HTML: + c.WriteHeader(http.StatusInternalServerError) + s.ErrorPage(c, err) + case JSON: + c.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(c).Encode(map[string]string{ + "error": err.Error(), + }) } } - signinPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, nil, "") - instance, ok := s.SingleInstance() - if ok { - url, sessionID, err := s.NewSession(instance) + authenticate := func(c *client, t authType) error { + if t >= SESSION { + cookie, err := c.Req.Cookie("session_id") + if err != nil || len(cookie.Value) < 1 { + return errInvalidSession + } + c.Session, err = s.sessionRepo.Get(cookie.Value) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return errInvalidSession } - - setSessionCookie(w, sessionID, sessionExp) - w.Header().Add("Location", url) - w.WriteHeader(http.StatusFound) - } else { - err := s.ServeSigninPage(c) + app, err := s.appRepo.Get(c.Session.InstanceDomain) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err + } + c.Client = mastodon.NewClient(&mastodon.Config{ + Server: app.InstanceURL, + ClientID: app.ClientID, + ClientSecret: app.ClientSecret, + AccessToken: c.Session.AccessToken, + }) + } + if t >= CSRF { + c.CSRFToken = c.Req.FormValue("csrf_token") + if len(c.CSRFToken) < 1 || c.CSRFToken != c.Session.CSRFToken { + return errInvalidCSRFToken } } + return nil } - timelinePage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - tType, _ := mux.Vars(req)["type"] - maxID := req.URL.Query().Get("max_id") - minID := req.URL.Query().Get("min_id") - - err := s.ServeTimelinePage(c, tType, maxID, minID) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - defaultTimelinePage := func(w http.ResponseWriter, req *http.Request) { - w.Header().Add("Location", "/timeline/home") - w.WriteHeader(http.StatusFound) - } - - threadPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - id, _ := mux.Vars(req)["id"] - reply := req.URL.Query().Get("reply") - - err := s.ServeThreadPage(c, id, len(reply) > 1) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - likedByPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - id, _ := mux.Vars(req)["id"] - - err := s.ServeLikedByPage(c, id) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - retweetedByPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - id, _ := mux.Vars(req)["id"] - - err := s.ServeRetweetedByPage(c, id) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - notificationsPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - maxID := req.URL.Query().Get("max_id") - minID := req.URL.Query().Get("min_id") - - err := s.ServeNotificationPage(c, maxID, minID) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } + handle := func(f func(c *client) error, at authType, rt respType) http.HandlerFunc { + return func(w http.ResponseWriter, req *http.Request) { + var err error + c := &client{Req: req, ResponseWriter: w} - userPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - id, _ := mux.Vars(req)["id"] - pageType, _ := mux.Vars(req)["type"] - maxID := req.URL.Query().Get("max_id") - minID := req.URL.Query().Get("min_id") + defer func(begin time.Time) { + logger.Printf("path=%s, err=%v, took=%v\n", + req.URL.Path, err, time.Since(begin)) + }(time.Now()) - err := s.ServeUserPage(c, id, pageType, maxID, minID) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - userSearchPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - id, _ := mux.Vars(req)["id"] - q := req.URL.Query().Get("q") - offsetStr := req.URL.Query().Get("offset") + var ct string + switch rt { + case HTML: + ct = "text/html; charset=utf-8" + case JSON: + ct = "application/json" + } + c.Header().Add("Content-Type", ct) - var offset int - var err error - if len(offsetStr) > 1 { - offset, err = strconv.Atoi(offsetStr) + err = authenticate(c, at) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) + writeError(c, err, rt) return } - } - err = s.ServeUserSearchPage(c, id, q, offset) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - aboutPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - - err := s.ServeAboutPage(c) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - emojisPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - - err := s.ServeEmojiPage(c) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } - } - - searchPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - q := req.URL.Query().Get("q") - qType := req.URL.Query().Get("type") - offsetStr := req.URL.Query().Get("offset") - - var offset int - var err error - if len(offsetStr) > 1 { - offset, err = strconv.Atoi(offsetStr) + err = f(c) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) + writeError(c, err, rt) return } } - - err = s.ServeSearchPage(c, q, qType, offset) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } } - settingsPage := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - - err := s.ServeSettingsPage(c) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + rootPage := handle(func(c *client) error { + sid, _ := c.Req.Cookie("session_id") + if sid == nil || len(sid.Value) < 0 { + redirect(c, "/signin") + return nil } - } - - signin := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, nil, "") - instance := req.FormValue("instance") - - url, sessionID, err := s.NewSession(instance) + session, err := s.sessionRepo.Get(sid.Value) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + if err == errInvalidSession { + redirect(c, "/signin") + return nil + } + return err } - - setSessionCookie(w, sessionID, sessionExp) - w.Header().Add("Location", url) - w.WriteHeader(http.StatusFound) - } - - oauthCallback := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - token := req.URL.Query().Get("code") - - _, _, err := s.Signin(c, "", token) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + if len(session.AccessToken) < 1 { + redirect(c, "/signin") + return nil } + return s.RootPage(c) + }, NOAUTH, HTML) - w.Header().Add("Location", "/") - w.WriteHeader(http.StatusFound) - } - - post := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, "") - err := req.ParseMultipartForm(4 << 20) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return - } + navPage := handle(func(c *client) error { + return s.NavPage(c) + }, SESSION, HTML) - c = newClient(w, req, - getMultipartFormValue(req.MultipartForm, "csrf_token")) - content := getMultipartFormValue(req.MultipartForm, "content") - replyToID := getMultipartFormValue(req.MultipartForm, "reply_to_id") - format := getMultipartFormValue(req.MultipartForm, "format") - visibility := getMultipartFormValue(req.MultipartForm, "visibility") - isNSFW := "on" == getMultipartFormValue(req.MultipartForm, "is_nsfw") - files := req.MultipartForm.File["attachments"] + signinPage := handle(func(c *client) error { + instance, ok := s.SingleInstance() + if !ok { + return s.SigninPage(c) + } + url, sid, err := s.NewSession(instance) + if err != nil { + return err + } + setSessionCookie(c, sid, sessionExp) + redirect(c, url) + return nil + }, NOAUTH, HTML) + + timelinePage := handle(func(c *client) error { + tType, _ := mux.Vars(c.Req)["type"] + q := c.Req.URL.Query() + maxID := q.Get("max_id") + minID := q.Get("min_id") + return s.TimelinePage(c, tType, maxID, minID) + return nil + }, SESSION, HTML) + + defaultTimelinePage := handle(func(c *client) error { + redirect(c, "/timeline/home") + return nil + }, SESSION, HTML) + + threadPage := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + q := c.Req.URL.Query() + reply := q.Get("reply") + return s.ThreadPage(c, id, len(reply) > 1) + }, SESSION, HTML) + + likedByPage := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + return s.LikedByPage(c, id) + }, SESSION, HTML) + + retweetedByPage := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + return s.RetweetedByPage(c, id) + }, SESSION, HTML) + + notificationsPage := handle(func(c *client) error { + q := c.Req.URL.Query() + maxID := q.Get("max_id") + minID := q.Get("min_id") + return s.NotificationPage(c, maxID, minID) + }, SESSION, HTML) + + userPage := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + pageType, _ := mux.Vars(c.Req)["type"] + q := c.Req.URL.Query() + maxID := q.Get("max_id") + minID := q.Get("min_id") + return s.UserPage(c, id, pageType, maxID, minID) + }, SESSION, HTML) + + userSearchPage := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + q := c.Req.URL.Query() + sq := q.Get("q") + offset, _ := strconv.Atoi(q.Get("offset")) + return s.UserSearchPage(c, id, sq, offset) + }, SESSION, HTML) + + aboutPage := handle(func(c *client) error { + return s.AboutPage(c) + }, SESSION, HTML) + + emojisPage := handle(func(c *client) error { + return s.EmojiPage(c) + }, SESSION, HTML) + + searchPage := handle(func(c *client) error { + q := c.Req.URL.Query() + sq := q.Get("q") + qType := q.Get("type") + offset, _ := strconv.Atoi(q.Get("offset")) + return s.SearchPage(c, sq, qType, offset) + }, SESSION, HTML) + + settingsPage := handle(func(c *client) error { + return s.SettingsPage(c) + }, SESSION, HTML) + + signin := handle(func(c *client) error { + instance := c.Req.FormValue("instance") + url, sid, err := s.NewSession(instance) + if err != nil { + return err + } + setSessionCookie(c, sid, sessionExp) + redirect(c, url) + return nil + }, NOAUTH, HTML) + + oauthCallback := handle(func(c *client) error { + q := c.Req.URL.Query() + token := q.Get("code") + token, userID, err := s.Signin(c, token) + if err != nil { + return err + } + + c.Session.AccessToken = token + c.Session.UserID = userID + err = s.sessionRepo.Add(c.Session) + if err != nil { + return err + } + + redirect(c, "/") + return nil + }, SESSION, HTML) + + post := handle(func(c *client) error { + content := c.Req.FormValue("content") + replyToID := c.Req.FormValue("reply_to_id") + format := c.Req.FormValue("format") + visibility := c.Req.FormValue("visibility") + isNSFW := c.Req.FormValue("is_nsfw") == "on" + files := c.Req.MultipartForm.File["attachments"] id, err := s.Post(c, content, replyToID, format, visibility, isNSFW, files) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } - location := req.Header.Get("Referer") + location := c.Req.Header.Get("Referer") if len(replyToID) > 0 { location = "/thread/" + replyToID + "#status-" + id } - w.Header().Add("Location", location) - w.WriteHeader(http.StatusFound) - } - - like := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - retweetedByID := req.FormValue("retweeted_by_id") + redirect(c, location) + return nil + }, CSRF, HTML) + like := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + rid := c.Req.FormValue("retweeted_by_id") _, err := s.Like(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } - - rID := id - if len(retweetedByID) > 0 { - rID = retweetedByID + if len(rid) > 0 { + id = rid } - w.Header().Add("Location", req.Header.Get("Referer")+"#status-"+rID) - w.WriteHeader(http.StatusFound) - } - - unlike := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - retweetedByID := req.FormValue("retweeted_by_id") + redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + return nil + }, CSRF, HTML) + unlike := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + rid := c.Req.FormValue("retweeted_by_id") _, err := s.UnLike(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } - - rID := id - if len(retweetedByID) > 0 { - rID = retweetedByID + if len(rid) > 0 { + id = rid } - w.Header().Add("Location", req.Header.Get("Referer")+"#status-"+rID) - w.WriteHeader(http.StatusFound) - } - - retweet := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - retweetedByID := req.FormValue("retweeted_by_id") + redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + return nil + }, CSRF, HTML) + retweet := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + rid := c.Req.FormValue("retweeted_by_id") _, err := s.Retweet(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } - - rID := id - if len(retweetedByID) > 0 { - rID = retweetedByID + if len(rid) > 0 { + id = rid } - w.Header().Add("Location", req.Header.Get("Referer")+"#status-"+rID) - w.WriteHeader(http.StatusFound) - } - - unretweet := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - retweetedByID := req.FormValue("retweeted_by_id") + redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + return nil + }, CSRF, HTML) + unretweet := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + rid := c.Req.FormValue("retweeted_by_id") _, err := s.UnRetweet(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } - - rID := id - if len(retweetedByID) > 0 { - rID = retweetedByID + if len(rid) > 0 { + id = rid } + redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")+"#status-"+rID) - w.WriteHeader(http.StatusFound) - } - - vote := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - statusID := req.FormValue("status_id") - choices, _ := req.PostForm["choices"] - + vote := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + statusID := c.Req.FormValue("status_id") + choices, _ := c.Req.PostForm["choices"] err := s.Vote(c, id, choices) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")+"#status-"+statusID) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")+"#status-"+statusID) - w.WriteHeader(http.StatusFound) - } - - follow := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + follow := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + q := c.Req.URL.Query() var reblogs *bool - r, ok := req.URL.Query()["reblogs"] - if ok && len(r) > 0 { + if r, ok := q["reblogs"]; ok && len(r) > 0 { reblogs = new(bool) *reblogs = r[0] == "true" } - err := s.Follow(c, id, reblogs) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - unfollow := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + unfollow := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.UnFollow(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - mute := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + mute := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.Mute(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - unMute := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + unMute := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.UnMute(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - block := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + block := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.Block(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - unBlock := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + unBlock := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.UnBlock(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - subscribe := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + subscribe := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.Subscribe(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - unSubscribe := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + unSubscribe := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.UnSubscribe(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - settings := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - visibility := req.FormValue("visibility") - format := req.FormValue("format") - copyScope := req.FormValue("copy_scope") == "true" - threadInNewTab := req.FormValue("thread_in_new_tab") == "true" - hideAttachments := req.FormValue("hide_attachments") == "true" - maskNSFW := req.FormValue("mask_nsfw") == "true" - ni, _ := strconv.Atoi(req.FormValue("notification_interval")) - fluorideMode := req.FormValue("fluoride_mode") == "true" - darkMode := req.FormValue("dark_mode") == "true" - antiDopamineMode := req.FormValue("anti_dopamine_mode") == "true" + settings := handle(func(c *client) error { + visibility := c.Req.FormValue("visibility") + format := c.Req.FormValue("format") + copyScope := c.Req.FormValue("copy_scope") == "true" + threadInNewTab := c.Req.FormValue("thread_in_new_tab") == "true" + hideAttachments := c.Req.FormValue("hide_attachments") == "true" + maskNSFW := c.Req.FormValue("mask_nsfw") == "true" + ni, _ := strconv.Atoi(c.Req.FormValue("notification_interval")) + fluorideMode := c.Req.FormValue("fluoride_mode") == "true" + darkMode := c.Req.FormValue("dark_mode") == "true" + antiDopamineMode := c.Req.FormValue("anti_dopamine_mode") == "true" settings := &model.Settings{ DefaultVisibility: visibility, @@ -609,192 +490,123 @@ func NewHandler(s Service, staticDir string) http.Handler { err := s.SaveSettings(c, settings) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, "/") + return nil + }, CSRF, HTML) - w.Header().Add("Location", "/") - w.WriteHeader(http.StatusFound) - } - - muteConversation := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + muteConversation := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.MuteConversation(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - unMuteConversation := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + unMuteConversation := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.UnMuteConversation(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - delete := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + delete := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] err := s.Delete(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - readNotifications := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - maxID := req.URL.Query().Get("max_id") - + readNotifications := handle(func(c *client) error { + q := c.Req.URL.Query() + maxID := q.Get("max_id") err := s.ReadNotifications(c, maxID) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) - w.Header().Add("Location", req.Header.Get("Referer")) - w.WriteHeader(http.StatusFound) - } - - bookmark := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - retweetedByID := req.FormValue("retweeted_by_id") - + bookmark := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + rid := c.Req.FormValue("retweeted_by_id") err := s.Bookmark(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } - - rID := id - if len(retweetedByID) > 0 { - rID = retweetedByID + if len(rid) > 0 { + id = rid } - w.Header().Add("Location", req.Header.Get("Referer")+"#status-"+rID) - w.WriteHeader(http.StatusFound) - } - - unBookmark := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - retweetedByID := req.FormValue("retweeted_by_id") + redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + return nil + }, CSRF, HTML) + unBookmark := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + rid := c.Req.FormValue("retweeted_by_id") err := s.UnBookmark(c, id) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - s.ServeErrorPage(c, err) - return + return err } - - rID := id - if len(retweetedByID) > 0 { - rID = retweetedByID + if len(rid) > 0 { + id = rid } - w.Header().Add("Location", req.Header.Get("Referer")+"#status-"+rID) - w.WriteHeader(http.StatusFound) - } - - signout := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) + redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + return nil + }, CSRF, HTML) + signout := handle(func(c *client) error { s.Signout(c) + setSessionCookie(c, "", 0) + redirect(c, "/") + return nil + }, CSRF, HTML) - setSessionCookie(w, "", 0) - w.Header().Add("Location", "/") - w.WriteHeader(http.StatusFound) - } - - fLike := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + fLike := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] count, err := s.Like(c, id) if err != nil { - serveJsonError(w, err) - return + return err } + return writeJson(c, count) + }, CSRF, JSON) - err = serveJson(w, count) - if err != nil { - serveJsonError(w, err) - return - } - } - - fUnlike := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] - + fUnlike := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] count, err := s.UnLike(c, id) if err != nil { - serveJsonError(w, err) - return - } - - err = serveJson(w, count) - if err != nil { - serveJsonError(w, err) - return + return err } - } - - fRetweet := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] + return writeJson(c, count) + }, CSRF, JSON) + fRetweet := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] count, err := s.Retweet(c, id) if err != nil { - serveJsonError(w, err) - return - } - - err = serveJson(w, count) - if err != nil { - serveJsonError(w, err) - return + return err } - } - - fUnretweet := func(w http.ResponseWriter, req *http.Request) { - c := newClient(w, req, req.FormValue("csrf_token")) - id, _ := mux.Vars(req)["id"] + return writeJson(c, count) + }, CSRF, JSON) + fUnretweet := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] count, err := s.UnRetweet(c, id) if err != nil { - serveJsonError(w, err) - return + return err } - - err = serveJson(w, count) - if err != nil { - serveJsonError(w, err) - return - } - } + return writeJson(c, count) + }, CSRF, JSON) r.HandleFunc("/", rootPage).Methods(http.MethodGet) r.HandleFunc("/nav", navPage).Methods(http.MethodGet) -- cgit v1.2.3 From 91f68ccfb391ee53bfc36f4877ca8d8f63c8faf2 Mon Sep 17 00:00:00 2001 From: r Date: Sat, 16 Jan 2021 09:10:02 +0000 Subject: Add follow request support --- service/transport.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'service/transport.go') diff --git a/service/transport.go b/service/transport.go index 80ad7f1..7ba52a4 100644 --- a/service/transport.go +++ b/service/transport.go @@ -403,6 +403,26 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { return nil }, CSRF, HTML) + accept := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + err := s.Accept(c, id) + if err != nil { + return err + } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) + + reject := handle(func(c *client) error { + id, _ := mux.Vars(c.Req)["id"] + err := s.Reject(c, id) + if err != nil { + return err + } + redirect(c, c.Req.Header.Get("Referer")) + return nil + }, CSRF, HTML) + mute := handle(func(c *client) error { id, _ := mux.Vars(c.Req)["id"] err := s.Mute(c, id) @@ -634,6 +654,8 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { r.HandleFunc("/vote/{id}", vote).Methods(http.MethodPost) r.HandleFunc("/follow/{id}", follow).Methods(http.MethodPost) r.HandleFunc("/unfollow/{id}", unfollow).Methods(http.MethodPost) + r.HandleFunc("/accept/{id}", accept).Methods(http.MethodPost) + r.HandleFunc("/reject/{id}", reject).Methods(http.MethodPost) r.HandleFunc("/mute/{id}", mute).Methods(http.MethodPost) r.HandleFunc("/unmute/{id}", unMute).Methods(http.MethodPost) r.HandleFunc("/block/{id}", block).Methods(http.MethodPost) -- cgit v1.2.3 From f4620a8c69a71a4e99ed4e51346ec630f7c3aee2 Mon Sep 17 00:00:00 2001 From: r Date: Sun, 17 Jan 2021 05:44:07 +0000 Subject: Make redirection work without Referer header --- service/transport.go | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'service/transport.go') diff --git a/service/transport.go b/service/transport.go index 7ba52a4..882a351 100644 --- a/service/transport.go +++ b/service/transport.go @@ -46,6 +46,10 @@ type client struct { Session model.Session } +func (c *client) url() string { + return c.Req.URL.RequestURI() +} + func setSessionCookie(w http.ResponseWriter, sid string, exp time.Duration) { http.SetCookie(w, &http.Cookie{ Name: "session_id", @@ -301,7 +305,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { return err } - location := c.Req.Header.Get("Referer") + location := c.Req.FormValue("referrer") if len(replyToID) > 0 { location = "/thread/" + replyToID + "#status-" + id } @@ -319,7 +323,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if len(rid) > 0 { id = rid } - redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + redirect(c, c.Req.FormValue("referrer")+"#status-"+id) return nil }, CSRF, HTML) @@ -333,7 +337,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if len(rid) > 0 { id = rid } - redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + redirect(c, c.Req.FormValue("referrer")+"#status-"+id) return nil }, CSRF, HTML) @@ -347,7 +351,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if len(rid) > 0 { id = rid } - redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + redirect(c, c.Req.FormValue("referrer")+"#status-"+id) return nil }, CSRF, HTML) @@ -361,7 +365,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if len(rid) > 0 { id = rid } - redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + redirect(c, c.Req.FormValue("referrer")+"#status-"+id) return nil }, CSRF, HTML) @@ -373,7 +377,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")+"#status-"+statusID) + redirect(c, c.Req.FormValue("referrer")+"#status-"+statusID) return nil }, CSRF, HTML) @@ -389,7 +393,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -399,7 +403,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -409,7 +413,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -419,7 +423,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -429,7 +433,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -439,7 +443,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -449,7 +453,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -459,7 +463,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -469,7 +473,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -479,7 +483,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -522,7 +526,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -532,7 +536,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -542,7 +546,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -553,7 +557,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if err != nil { return err } - redirect(c, c.Req.Header.Get("Referer")) + redirect(c, c.Req.FormValue("referrer")) return nil }, CSRF, HTML) @@ -567,7 +571,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if len(rid) > 0 { id = rid } - redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + redirect(c, c.Req.FormValue("referrer")+"#status-"+id) return nil }, CSRF, HTML) @@ -581,7 +585,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { if len(rid) > 0 { id = rid } - redirect(c, c.Req.Header.Get("Referer")+"#status-"+id) + redirect(c, c.Req.FormValue("referrer")+"#status-"+id) return nil }, CSRF, HTML) -- cgit v1.2.3 From ac342dde079a0ca156c36a402a3c0ba86d78821d Mon Sep 17 00:00:00 2001 From: r Date: Sat, 23 Jan 2021 08:44:05 +0000 Subject: Add remote timeline --- service/transport.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service/transport.go') diff --git a/service/transport.go b/service/transport.go index 882a351..096b44e 100644 --- a/service/transport.go +++ b/service/transport.go @@ -190,10 +190,10 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler { timelinePage := handle(func(c *client) error { tType, _ := mux.Vars(c.Req)["type"] q := c.Req.URL.Query() + instance := q.Get("instance") maxID := q.Get("max_id") minID := q.Get("min_id") - return s.TimelinePage(c, tType, maxID, minID) - return nil + return s.TimelinePage(c, tType, instance, maxID, minID) }, SESSION, HTML) defaultTimelinePage := handle(func(c *client) error { -- cgit v1.2.3