2019-12-13 18:08:26 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
2019-12-14 20:19:02 +00:00
|
|
|
"mime/multipart"
|
2020-01-01 15:58:27 +00:00
|
|
|
|
2020-02-01 11:31:44 +00:00
|
|
|
"bloat/mastodon"
|
2020-01-01 15:58:27 +00:00
|
|
|
"bloat/model"
|
2019-12-13 18:08:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2020-01-28 17:51:00 +00:00
|
|
|
errInvalidSession = errors.New("invalid session")
|
|
|
|
errInvalidCSRFToken = errors.New("invalid csrf token")
|
2019-12-13 18:08:26 +00:00
|
|
|
)
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
type as struct {
|
|
|
|
sessionRepo model.SessionRepo
|
|
|
|
appRepo model.AppRepo
|
2019-12-13 18:08:26 +00:00
|
|
|
Service
|
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func NewAuthService(sessionRepo model.SessionRepo, appRepo model.AppRepo, s Service) Service {
|
|
|
|
return &as{sessionRepo, appRepo, s}
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) authenticateClient(ctx context.Context, c *model.Client) (err error) {
|
2019-12-13 18:08:26 +00:00
|
|
|
sessionID, ok := ctx.Value("session_id").(string)
|
|
|
|
if !ok || len(sessionID) < 1 {
|
2020-01-28 17:51:00 +00:00
|
|
|
return errInvalidSession
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
session, err := s.sessionRepo.Get(sessionID)
|
|
|
|
if err != nil {
|
2020-01-28 17:51:00 +00:00
|
|
|
return errInvalidSession
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
2019-12-17 20:17:25 +00:00
|
|
|
client, err := s.appRepo.Get(session.InstanceDomain)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2019-12-21 11:13:21 +00:00
|
|
|
mc := mastodon.NewClient(&mastodon.Config{
|
2019-12-17 20:17:25 +00:00
|
|
|
Server: client.InstanceURL,
|
2019-12-13 18:08:26 +00:00
|
|
|
ClientID: client.ClientID,
|
|
|
|
ClientSecret: client.ClientSecret,
|
|
|
|
AccessToken: session.AccessToken,
|
|
|
|
})
|
2020-01-28 17:51:00 +00:00
|
|
|
if c == nil {
|
|
|
|
c = &model.Client{}
|
|
|
|
}
|
|
|
|
c.Client = mc
|
|
|
|
c.Session = session
|
|
|
|
return nil
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-25 10:07:06 +00:00
|
|
|
func checkCSRF(ctx context.Context, c *model.Client) (err error) {
|
2020-01-28 17:51:00 +00:00
|
|
|
token, ok := ctx.Value("csrf_token").(string)
|
|
|
|
if !ok || token != c.Session.CSRFToken {
|
|
|
|
return errInvalidCSRFToken
|
2020-01-25 10:07:06 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeErrorPage(ctx context.Context, c *model.Client, err error) {
|
|
|
|
s.authenticateClient(ctx, c)
|
|
|
|
s.Service.ServeErrorPage(ctx, c, err)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeSigninPage(ctx context.Context, c *model.Client) (err error) {
|
|
|
|
return s.Service.ServeSigninPage(ctx, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *as) ServeTimelinePage(ctx context.Context, c *model.Client, tType string,
|
|
|
|
maxID string, minID string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeTimelinePage(ctx, c, tType, maxID, minID)
|
|
|
|
}
|
2019-12-13 18:08:26 +00:00
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeThreadPage(ctx context.Context, c *model.Client, id string, reply bool) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeThreadPage(ctx, c, id, reply)
|
|
|
|
}
|
2019-12-13 18:08:26 +00:00
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeLikedByPage(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeLikedByPage(ctx, c, id)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeRetweetedByPage(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeRetweetedByPage(ctx, c, id)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeNotificationPage(ctx context.Context, c *model.Client,
|
|
|
|
maxID string, minID string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-20 18:30:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeNotificationPage(ctx, c, maxID, minID)
|
2019-12-20 18:30:20 +00:00
|
|
|
}
|
|
|
|
|
2020-02-01 11:31:44 +00:00
|
|
|
func (s *as) ServeUserPage(ctx context.Context, c *model.Client, id string,
|
2020-01-31 03:38:49 +00:00
|
|
|
pageType string, maxID string, minID string) (err error) {
|
2020-01-28 17:51:00 +00:00
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-21 05:48:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-31 03:38:49 +00:00
|
|
|
return s.Service.ServeUserPage(ctx, c, id, pageType, maxID, minID)
|
2019-12-21 05:48:48 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeAboutPage(ctx context.Context, c *model.Client) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-22 18:10:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeAboutPage(ctx, c)
|
2019-12-22 18:10:42 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeEmojiPage(ctx context.Context, c *model.Client) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-26 09:11:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeEmojiPage(ctx, c)
|
2019-12-26 09:11:24 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeSearchPage(ctx context.Context, c *model.Client, q string,
|
|
|
|
qType string, offset int) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-26 09:11:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeSearchPage(ctx, c, q, qType, offset)
|
2019-12-26 09:11:24 +00:00
|
|
|
}
|
|
|
|
|
2020-02-01 11:31:44 +00:00
|
|
|
func (s *as) ServeUserSearchPage(ctx context.Context, c *model.Client,
|
2020-01-30 15:32:37 +00:00
|
|
|
id string, q string, offset int) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.ServeUserSearchPage(ctx, c, id, q, offset)
|
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) ServeSettingsPage(ctx context.Context, c *model.Client) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-29 03:43:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.ServeSettingsPage(ctx, c)
|
2019-12-29 03:43:57 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) NewSession(ctx context.Context, instance string) (redirectUrl string,
|
|
|
|
sessionID string, err error) {
|
|
|
|
return s.Service.NewSession(ctx, instance)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *as) Signin(ctx context.Context, c *model.Client, sessionID string,
|
2020-02-02 08:30:40 +00:00
|
|
|
code string) (token string, userID string, err error) {
|
2020-01-28 17:51:00 +00:00
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-29 03:43:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-02-02 08:30:40 +00:00
|
|
|
token, userID, err = s.Service.Signin(ctx, c, c.Session.ID, code)
|
2019-12-26 19:18:09 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
c.Session.AccessToken = token
|
2020-02-02 08:30:40 +00:00
|
|
|
c.Session.UserID = userID
|
2020-01-28 17:51:00 +00:00
|
|
|
err = s.sessionRepo.Add(c.Session)
|
2019-12-27 08:06:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
|
|
|
|
return
|
2019-12-27 08:06:43 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) Post(ctx context.Context, c *model.Client, content string,
|
|
|
|
replyToID string, format string, visibility string, isNSFW bool,
|
|
|
|
files []*multipart.FileHeader) (id string, err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-27 08:06:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.Post(ctx, c, content, replyToID, format, visibility, isNSFW, files)
|
2019-12-27 08:06:43 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) Like(ctx context.Context, c *model.Client, id string) (count int64, err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.Like(ctx, c, id)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) UnLike(ctx context.Context, c *model.Client, id string) (count int64, err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.UnLike(ctx, c, id)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) Retweet(ctx context.Context, c *model.Client, id string) (count int64, err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.Retweet(ctx, c, id)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) UnRetweet(ctx context.Context, c *model.Client, id string) (count int64, err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.UnRetweet(ctx, c, id)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) Follow(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-13 18:08:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.Follow(ctx, c, id)
|
2019-12-13 18:08:26 +00:00
|
|
|
}
|
2019-12-20 18:30:20 +00:00
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) UnFollow(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-20 18:30:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.UnFollow(ctx, c, id)
|
2019-12-20 18:30:20 +00:00
|
|
|
}
|
|
|
|
|
2020-02-08 10:49:06 +00:00
|
|
|
func (s *as) Mute(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.Mute(ctx, c, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *as) UnMute(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.UnMute(ctx, c, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *as) Block(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.Block(ctx, c, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *as) UnBlock(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.UnBlock(ctx, c, id)
|
|
|
|
}
|
|
|
|
|
2020-01-28 17:51:00 +00:00
|
|
|
func (s *as) SaveSettings(ctx context.Context, c *model.Client, settings *model.Settings) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
2019-12-20 18:30:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-25 10:07:06 +00:00
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-01-28 17:51:00 +00:00
|
|
|
return s.Service.SaveSettings(ctx, c, settings)
|
2019-12-20 18:30:20 +00:00
|
|
|
}
|
2020-02-02 07:24:06 +00:00
|
|
|
|
|
|
|
func (s *as) MuteConversation(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.MuteConversation(ctx, c, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *as) UnMuteConversation(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.UnMuteConversation(ctx, c, id)
|
|
|
|
}
|
2020-02-02 08:30:40 +00:00
|
|
|
|
|
|
|
func (s *as) Delete(ctx context.Context, c *model.Client, id string) (err error) {
|
|
|
|
err = s.authenticateClient(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = checkCSRF(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return s.Service.Delete(ctx, c, id)
|
|
|
|
}
|