144 lines
3.3 KiB
Go
144 lines
3.3 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package consoleapi
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"go.uber.org/zap"
|
|
monkit "gopkg.in/spacemonkeygo/monkit.v2"
|
|
|
|
"storj.io/storj/pkg/auth"
|
|
"storj.io/storj/satellite/console"
|
|
)
|
|
|
|
var mon = monkit.Package()
|
|
|
|
// Payments is an api controller that exposes all payment related functionality
|
|
type Payments struct {
|
|
log *zap.Logger
|
|
service *console.Service
|
|
}
|
|
|
|
// NewPayments is a constructor for api payments controller.
|
|
func NewPayments(log *zap.Logger, service *console.Service) *Payments {
|
|
return &Payments{
|
|
log: log,
|
|
service: service,
|
|
}
|
|
}
|
|
|
|
// SetupAccount creates a payment account for the user.
|
|
func (p *Payments) SetupAccount(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
var err error
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
if r.Method != http.MethodPost {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
ctx = p.authorize(ctx, r)
|
|
|
|
err = p.service.Payments().SetupAccount(ctx)
|
|
if err != nil {
|
|
p.serveJSONError(w, http.StatusInternalServerError, err)
|
|
}
|
|
}
|
|
|
|
// AccountBalance returns an integer amount in cents that represents the current balance of payment account.
|
|
func (p *Payments) AccountBalance(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
var err error
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
if r.Method != http.MethodGet {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
ctx = p.authorize(ctx, r)
|
|
|
|
balance, err := p.service.Payments().AccountBalance(ctx)
|
|
if err != nil {
|
|
p.serveJSONError(w, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
var balanceResponse struct {
|
|
Balance int64 `json:"balance"`
|
|
}
|
|
|
|
balanceResponse.Balance = balance
|
|
|
|
err = json.NewEncoder(w).Encode(balanceResponse)
|
|
if err != nil {
|
|
p.log.Error("failed to write json balance response", zap.Error(err))
|
|
}
|
|
}
|
|
|
|
// AddCreditCard is used to save new credit card and attach it to payment account.
|
|
func (p *Payments) AddCreditCard(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
var err error
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
if r.Method != http.MethodPost {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
ctx = p.authorize(ctx, r)
|
|
|
|
var requestBody struct {
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
decoder := json.NewDecoder(r.Body)
|
|
|
|
err = decoder.Decode(&requestBody)
|
|
if err != nil {
|
|
p.serveJSONError(w, http.StatusBadRequest, err)
|
|
return
|
|
}
|
|
|
|
err = p.service.Payments().AddCreditCard(ctx, requestBody.Token)
|
|
if err != nil {
|
|
p.serveJSONError(w, http.StatusInternalServerError, err)
|
|
}
|
|
}
|
|
|
|
// serveJSONError writes JSON error to response output stream.
|
|
func (p *Payments) serveJSONError(w http.ResponseWriter, status int, err error) {
|
|
w.WriteHeader(status)
|
|
|
|
var response struct {
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
response.Error = err.Error()
|
|
|
|
err = json.NewEncoder(w).Encode(response)
|
|
if err != nil {
|
|
p.log.Error("failed to write json error response", zap.Error(err))
|
|
}
|
|
}
|
|
|
|
// authorize checks request for authorization token, validates it and updates context with auth data.
|
|
func (p *Payments) authorize(ctx context.Context, r *http.Request) context.Context {
|
|
authHeaderValue := r.Header.Get("Authorization")
|
|
token := strings.TrimPrefix(authHeaderValue, "Bearer ")
|
|
|
|
auth, err := p.service.Authorize(auth.WithAPIKey(ctx, []byte(token)))
|
|
if err != nil {
|
|
return console.WithAuthFailure(ctx, err)
|
|
}
|
|
|
|
return console.WithAuth(ctx, auth)
|
|
}
|