diff --git a/apps.go b/apps.go index b03f9b1..d113909 100644 --- a/apps.go +++ b/apps.go @@ -94,3 +94,20 @@ func RegisterApp(ctx context.Context, appConfig *AppConfig) (*Application, error return &app, nil } + +// ApplicationVerification is mastodon application. +type ApplicationVerification struct { + Name string `json:"name"` + Website string `json:"website"` + VapidKey string `json:"vapid_key"` +} + +// VerifyAppCredentials returns the mastodon application. +func (c *Client) VerifyAppCredentials(ctx context.Context) (*ApplicationVerification, error) { + var application ApplicationVerification + err := c.doAPI(ctx, http.MethodGet, "/api/v1/apps/verify_credentials", nil, &application, nil) + if err != nil { + return nil, err + } + return &application, nil +} diff --git a/apps_test.go b/apps_test.go index 32e28ab..8734234 100644 --- a/apps_test.go +++ b/apps_test.go @@ -96,3 +96,49 @@ func TestRegisterAppWithCancel(t *testing.T) { t.Fatalf("want %q but %q", want, err.Error()) } } + +func TestVerifyAppCredentials(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") != "Bearer zoo" { + http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) + return + } + if r.URL.Path != "/api/v1/apps/verify_credentials" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + fmt.Fprintln(w, `{"name":"zzz","website":"yyy","vapid_key":"xxx"}`) + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zip", + }) + _, err := client.VerifyAppCredentials(context.Background()) + if err == nil { + t.Fatalf("should be fail: %v", err) + } + + client = NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + a, err := client.VerifyAppCredentials(context.Background()) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if a.Name != "zzz" { + t.Fatalf("want %q but %q", "zzz", a.Name) + } + if a.Website != "yyy" { + t.Fatalf("want %q but %q", "yyy", a.Name) + } + if a.VapidKey != "xxx" { + t.Fatalf("want %q but %q", "xxx", a.Name) + } +} diff --git a/mastodon.go b/mastodon.go index 3523713..5b43308 100644 --- a/mastodon.go +++ b/mastodon.go @@ -150,6 +150,18 @@ func (c *Client) Authenticate(ctx context.Context, username, password string) er return c.authenticate(ctx, params) } +// AuthenticateApp logs in using client credentials. +func (c *Client) AuthenticateApp(ctx context.Context) error { + params := url.Values{ + "client_id": {c.Config.ClientID}, + "client_secret": {c.Config.ClientSecret}, + "grant_type": {"client_credentials"}, + "redirect_uri": {"urn:ietf:wg:oauth:2.0:oob"}, + } + + 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/mastodon_test.go b/mastodon_test.go index 9a8f3e3..527dd89 100644 --- a/mastodon_test.go +++ b/mastodon_test.go @@ -144,6 +144,38 @@ func TestAuthenticateWithCancel(t *testing.T) { } } +func TestAuthenticateApp(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.FormValue("client_id") != "foo" || r.FormValue("client_secret") != "bar" { + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + return + } + fmt.Fprintln(w, `{"name":"zzz","website":"yyy","vapid_key":"xxx"}`) + return + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bat", + }) + err := client.AuthenticateApp(context.Background()) + if err == nil { + t.Fatalf("should be fail: %v", err) + } + + client = NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + }) + err = client.AuthenticateApp(context.Background()) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } +} + func TestPostStatus(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Authorization") != "Bearer zoo" {