From 0f060f09c91915187c3f6b3a4ac694d1a8659f54 Mon Sep 17 00:00:00 2001
From: localhost_frssoft
Date: Sun, 13 Nov 2022 00:00:02 +0300
Subject: [PATCH] Added sign up support. Tested on mastodon
But required test on GoToSocial.
Confirmation inside bloat-fe not supported
---
mastodon/accounts.go | 68 +++++++++++++++++++++++++++++++++++++++++++
mastodon/apps.go | 50 +++++++++++++++++++++++++++++--
mastodon/mastodon.go | 2 ++
service/service.go | 66 +++++++++++++++++++++++++++++++++++++++++
service/transport.go | 27 +++++++++++++++++
templates/signin.tmpl | 33 +++++++++++++++++++++
6 files changed, 244 insertions(+), 2 deletions(-)
diff --git a/mastodon/accounts.go b/mastodon/accounts.go
index acf1d04..76b72b6 100644
--- a/mastodon/accounts.go
+++ b/mastodon/accounts.go
@@ -3,10 +3,13 @@ package mastodon
import (
"context"
"fmt"
+ "encoding/json"
"net/http"
"net/url"
"strconv"
"time"
+ "strings"
+ "path"
)
type AccountPleroma struct {
@@ -59,6 +62,71 @@ type AccountSource struct {
Fields *[]Field `json:"fields"`
}
+type RegisterCredintals struct {
+ http.Client
+ Server string
+ App *Application
+ Reason string
+ Username string
+ Email string
+ Password string
+ Agreement bool
+ Locale string
+}
+
+// Use for register account on GoToSocial
+type Registred struct {
+ AccessToken string `json:"access_token"`
+ CreatedAt int64 `json:"created_at"`
+ Scope string `json:"scope"`
+ TokenType string `json:"token_type"`
+}
+
+
+// RegisterAccount create new account
+func RegisterAccount(ctx context.Context, instance string, reason string, username string, email string, password string, agreement bool, locale string, registerCrendintals RegisterCredintals, bearer string) (*string, error) {
+ var registred Registred
+ params := url.Values{}
+ params.Set("reason", reason)
+ params.Set("username", username)
+ params.Set("email", email)
+ params.Set("password", password)
+ params.Set("agreement", strconv.FormatBool(agreement))
+ params.Set("locale", locale)
+ u, err := url.Parse("https://" + instance)
+ if err != nil {
+ return nil, err
+ }
+ u.Path = path.Join(u.Path, "/api/v1/accounts")
+
+ req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(params.Encode()))
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Set("Authorization", "Bearer "+bearer)
+ resp, err := registerCrendintals.Do(req)
+ fmt.Println(req)
+ fmt.Println(resp)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, parseAPIError("bad request", resp)
+ }
+
+ err = json.NewDecoder(resp.Body).Decode(®istred)
+ fmt.Println(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ return ®istred.AccessToken, nil
+}
+
+
// GetAccount return Account.
func (c *Client) GetAccount(ctx context.Context, id string) (*Account, error) {
var account Account
diff --git a/mastodon/apps.go b/mastodon/apps.go
index 4065ebf..ca24e0b 100644
--- a/mastodon/apps.go
+++ b/mastodon/apps.go
@@ -48,7 +48,6 @@ func RegisterApp(ctx context.Context, appConfig *AppConfig) (*Application, error
params.Set("redirect_uris", appConfig.RedirectURIs)
}
params.Set("scopes", appConfig.Scopes)
- params.Set("website", "https://gitea.phreedom.club/localhost_frssoft/bloat/src/branch/localhost_custom")
u, err := url.Parse(appConfig.Server)
if err != nil {
@@ -71,7 +70,7 @@ func RegisterApp(ctx context.Context, appConfig *AppConfig) (*Application, error
if resp.StatusCode != http.StatusOK {
return nil, parseAPIError("bad request", resp)
}
-
+
var app Application
err = json.NewDecoder(resp.Body).Decode(&app)
if err != nil {
@@ -94,3 +93,50 @@ func RegisterApp(ctx context.Context, appConfig *AppConfig) (*Application, error
return &app, nil
}
+
+type AppAuth struct {
+ http.Client
+}
+
+// RegisterApp make auth application and return app token.
+func AuthApp(ctx context.Context, appConfig *Application, instance string) (*string, error) {
+ var appAuth AppAuth
+ params := url.Values{}
+ params.Set("client_id", appConfig.ClientID)
+ params.Set("client_secret", appConfig.ClientSecret)
+ params.Set("redirect_uris", "urn:ietf:wg:oauth:2.0:oob")
+ params.Set("grant_type", "client_credentials")
+ params.Set("scope", "read write follow")
+
+ u, err := url.Parse("https://" + instance)
+ if err != nil {
+ return nil, err
+ }
+ u.Path = path.Join(u.Path, "/oauth/token")
+
+ req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(params.Encode()))
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ resp, err := appAuth.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, parseAPIError("bad request", resp)
+ }
+
+ var res struct {
+ AccessToken string `json:"access_token"`
+ }
+ err = json.NewDecoder(resp.Body).Decode(&res)
+ if err != nil {
+ return nil, err
+ }
+
+ return &res.AccessToken, nil
+}
diff --git a/mastodon/mastodon.go b/mastodon/mastodon.go
index 75e029b..3c2a6bb 100644
--- a/mastodon/mastodon.go
+++ b/mastodon/mastodon.go
@@ -202,6 +202,8 @@ func (c *Client) Authenticate(ctx context.Context, username, password string) er
return c.authenticate(ctx, params)
}
+
+
// AuthenticateToken logs in using a grant token returned by Application.AuthURI.
//
// redirectURI should be the same as Application.RedirectURI.
diff --git a/service/service.go b/service/service.go
index f8e3ff2..550d49d 100644
--- a/service/service.go
+++ b/service/service.go
@@ -920,6 +920,72 @@ func (s *service) Signin(c *client, code string) (err error) {
return c.setSession(c.s)
}
+func (s *service) NewSessionRegister(c *client, instance string, reason string, username string, email string, password string, agreement bool, locale string, registerCredintals mastodon.RegisterCredintals) (rurl string, sess *model.Session, err error) {
+ var instanceURL string
+ if strings.HasPrefix(instance, "https://") {
+ instanceURL = instance
+ instance = strings.TrimPrefix(instance, "https://")
+ } else {
+ instanceURL = "https://" + instance
+ }
+
+ sid, err := util.NewSessionID()
+ if err != nil {
+ return
+ }
+ csrf, err := util.NewCSRFToken()
+ if err != nil {
+ return
+ }
+
+ app, err := mastodon.RegisterApp(c.ctx, &mastodon.AppConfig{
+ Server: instanceURL,
+ ClientName: s.cname,
+ Scopes: s.cscope,
+ Website: s.cwebsite,
+ RedirectURIs: s.cwebsite + "/oauth_callback",
+ })
+ if err != nil {
+ return
+ }
+ registerCredintals.App = app
+ bearer, err := mastodon.AuthApp(c.ctx, app, instance)
+ if err != nil {
+ return
+ }
+ token, err := mastodon.RegisterAccount(c.ctx, instance, reason, username, email, password, agreement, locale, registerCredintals, *bearer)
+
+ if err != nil {
+ return
+ }
+ sess = &model.Session{
+ ID: sid,
+ Instance: instance,
+ UserID: "1",
+ ClientID: app.ClientID,
+ ClientSecret: app.ClientSecret,
+ AccessToken: *token,
+ CSRFToken: csrf,
+ Settings: *model.NewSettings(),
+ }
+
+ u, err := url.Parse("/oauth/authorize")
+ if err != nil {
+ return
+ }
+
+ q := make(url.Values)
+ q.Set("scope", "read write follow")
+ q.Set("client_id", app.ClientID)
+ q.Set("response_type", "code")
+ q.Set("redirect_uri", s.cwebsite+"/oauth_callback")
+ u.RawQuery = q.Encode()
+
+ rurl = instanceURL + u.String()
+ return
+}
+
+
func (s *service) Post(c *client, content string, replyToID string,
format string, visibility string, isNSFW bool, spoilerText string,
files []*multipart.FileHeader, edit string) (id string, err error) {
diff --git a/service/transport.go b/service/transport.go
index 697281f..6b20559 100644
--- a/service/transport.go
+++ b/service/transport.go
@@ -254,6 +254,32 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler {
return nil
}, NOAUTH, HTML)
+ signup := handle(func(c *client) error {
+ instance := c.r.FormValue("instanceup")
+ reason := c.r.FormValue("reason")
+ username := c.r.FormValue("username")
+ email := c.r.FormValue("email")
+ password := c.r.FormValue("password")
+ agreement := c.r.FormValue("agreement") == "true"
+ locale := c.r.FormValue("locale")
+ url, sess, err := s.NewSessionRegister(c, instance, reason, username, email, password, agreement, locale, mastodon.RegisterCredintals{
+ Server: "https://"+instance,
+ Reason: reason,
+ Username: username,
+ Email: email,
+ Password: password,
+ Agreement: agreement,
+ Locale: locale,
+ })
+ if err != nil {
+ return err
+ }
+ c.setSession(sess)
+ url = "/confirmation"
+ c.redirect(url)
+ return nil
+ }, NOAUTH, HTML)
+
oauthCallback := handle(func(c *client) error {
q := c.r.URL.Query()
token := q.Get("code")
@@ -786,6 +812,7 @@ func NewHandler(s *service, logger *log.Logger, staticDir string) http.Handler {
r.HandleFunc("/settings", settingsPage).Methods(http.MethodGet)
r.HandleFunc("/filters", filtersPage).Methods(http.MethodGet)
r.HandleFunc("/signin", signin).Methods(http.MethodPost)
+ r.HandleFunc("/signup", signup).Methods(http.MethodPost)
r.HandleFunc("/oauth_callback", oauthCallback).Methods(http.MethodGet)
r.HandleFunc("/post", post).Methods(http.MethodPost)
r.HandleFunc("/like/{id}", like).Methods(http.MethodPost)
diff --git a/templates/signin.tmpl b/templates/signin.tmpl
index c7699f7..5d66772 100644
--- a/templates/signin.tmpl
+++ b/templates/signin.tmpl
@@ -18,6 +18,39 @@
git.freesoftwareextremist.com/bloat
for more details.
+
+Sign up
+
+
+
+
{{template "footer.tmpl"}}
{{end}}