bloat/service/client.go
localhost_frssoft f9702f81a9 Merge patch and add useredit template...
Patch from: https://git.freesoftwareextremist.com/bloat/commit/?id=887ed241d64ba5db3fd3d87194fb5595e5ad7d73
Patch description:
Use cookies for session
Remove the server side session storage and store all the session related data
in the client side cookies. This decreases the exposure of the auth tokens.
It also simplifies the installation process as bloat no longer requires write
access to the filesystem.

This is a breaking change, all the existing sessions will stop working.
2022-11-12 01:20:49 +03:00

114 lines
2.5 KiB
Go

package service
import (
"context"
"encoding/base64"
"encoding/json"
"net/http"
"strings"
"time"
"bloat/mastodon"
"bloat/model"
"bloat/renderer"
)
type client struct {
*mastodon.Client
w http.ResponseWriter
r *http.Request
s *model.Session
csrf string
ctx context.Context
rctx *renderer.Context
}
func (c *client) setSession(sess *model.Session) error {
var sb strings.Builder
bw := base64.NewEncoder(base64.URLEncoding, &sb)
err := json.NewEncoder(bw).Encode(sess)
bw.Close()
if err != nil {
return err
}
http.SetCookie(c.w, &http.Cookie{
Name: "session",
Value: sb.String(),
Expires: time.Now().Add(365 * 24 * time.Hour),
})
return nil
}
func (c *client) getSession() (sess *model.Session, err error) {
cookie, _ := c.r.Cookie("session")
if cookie == nil {
return nil, errInvalidSession
}
br := base64.NewDecoder(base64.URLEncoding, strings.NewReader(cookie.Value))
err = json.NewDecoder(br).Decode(&sess)
return
}
func (c *client) unsetSession() {
http.SetCookie(c.w, &http.Cookie{
Name: "session",
Value: "",
Expires: time.Now(),
})
}
func (c *client) writeJson(data interface{}) error {
return json.NewEncoder(c.w).Encode(map[string]interface{}{
"data": data,
})
}
func (c *client) redirect(url string) {
c.w.Header().Add("Location", url)
c.w.WriteHeader(http.StatusFound)
}
func (c *client) authenticate(t int) (err error) {
csrf := c.r.FormValue("csrf_token")
ref := c.r.URL.RequestURI()
defer func() {
if c.s == nil {
c.s = &model.Session{
Settings: *model.NewSettings(),
}
}
c.rctx = &renderer.Context{
HideAttachments: c.s.Settings.HideAttachments,
MaskNSFW: c.s.Settings.MaskNSFW,
ThreadInNewTab: c.s.Settings.ThreadInNewTab,
FluorideMode: c.s.Settings.FluorideMode,
DarkMode: c.s.Settings.DarkMode,
CSRFToken: c.s.CSRFToken,
UserID: c.s.UserID,
AntiDopamineMode: c.s.Settings.AntiDopamineMode,
InstanceEmojiFilter: c.s.Settings.InstanceEmojiFilter,
AddReactionsFilter: c.s.Settings.AddReactionsFilter,
UserCSS: c.s.Settings.CSS,
Referrer: ref,
}
}()
if t < SESSION {
return
}
sess, err := c.getSession()
if err != nil {
return err
}
c.s = sess
c.Client = mastodon.NewClient(&mastodon.Config{
Server: "https://" + c.s.Instance,
ClientID: c.s.ClientID,
ClientSecret: c.s.ClientSecret,
AccessToken: c.s.AccessToken,
})
if t >= CSRF && (len(csrf) < 1 || csrf != c.s.CSRFToken) {
return errInvalidCSRFToken
}
return
}