aboutsummaryrefslogtreecommitdiff
path: root/service/client.go
blob: 18ebb5217b85f784a44a2bc7b483da24905f37b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package service

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"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",
		Path:     "/",
		HttpOnly: true,
		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",
		Path:    "/",
		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, instance string) (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,
			UserCSS:          c.s.Settings.CSS,
			Referrer:         ref,
		}
	}()
	if t < SESSION {
		return
	}
	sess, err := c.getSession()
	if err != nil {
		return err
	}
	c.s = sess
	if len(instance) > 0 && c.s.Instance != instance {
		return errors.New("invalid instance")
	}
	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
}