auth/internal/ticket/usecase/ticket_ucase.go

73 lines
1.9 KiB
Go

package usecase
import (
"context"
"encoding/json"
"fmt"
http "github.com/valyala/fasthttp"
"source.toby3d.me/website/indieauth/internal/common"
"source.toby3d.me/website/indieauth/internal/domain"
"source.toby3d.me/website/indieauth/internal/ticket"
)
type (
//nolint: tagliatelle
Response struct {
Me *domain.Me `json:"me"`
Scope domain.Scopes `json:"scope"`
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
}
ticketUseCase struct {
client *http.Client
repo ticket.Repository
}
)
func NewTicketUseCase(repo ticket.Repository, client *http.Client) ticket.UseCase {
return &ticketUseCase{
client: client,
repo: repo,
}
}
func (useCase *ticketUseCase) Redeem(ctx context.Context, ticket *domain.Ticket) (*domain.Token, error) {
endpoint, err := useCase.repo.Get(ctx, ticket.Resource)
if err != nil {
return nil, fmt.Errorf("cannot discovery token endpoint: %w", err)
}
req := http.AcquireRequest()
defer http.ReleaseRequest(req)
req.Header.SetMethod(http.MethodPost)
req.SetRequestURIBytes(endpoint.FullURI())
req.Header.SetContentType(common.MIMEApplicationForm)
req.Header.Set(http.HeaderAccept, common.MIMEApplicationJSON)
req.PostArgs().Set("grant_type", domain.GrantTypeTicket.String())
req.PostArgs().Set("ticket", ticket.Ticket)
resp := http.AcquireResponse()
defer http.ReleaseResponse(resp)
if err := useCase.client.Do(req, resp); err != nil {
return nil, err
}
data := new(Response)
if err := json.Unmarshal(resp.Body(), data); err != nil {
return nil, fmt.Errorf("cannot unmarshal access token response: %w", err)
}
// TODO(toby3d): should this also include client_id?
// https://github.com/indieweb/indieauth/issues/85
return &domain.Token{
ClientID: nil,
AccessToken: data.AccessToken,
Me: data.Me,
Scope: data.Scope,
}, nil
}