2021-01-14 16:41:36 +00:00
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package consoleapi
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/zeebo/errs"
"go.uber.org/zap"
"storj.io/common/storj"
"storj.io/storj/storagenode/payouts"
)
// ErrPayoutAPI - console payouts api error type.
var ErrPayoutAPI = errs . Class ( "payouts console web error" )
// Payout is an api controller that exposes all payouts related api.
type Payout struct {
service * payouts . Service
log * zap . Logger
}
// NewPayout is a constructor for payouts controller.
func NewPayout ( log * zap . Logger , service * payouts . Service ) * Payout {
return & Payout {
log : log ,
service : service ,
}
}
// PayStubMonthly returns payouts, storage holding and prices data for specific month from all satellites or specified satellite by query parameter id.
func ( payout * Payout ) PayStubMonthly ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
segmentParams := mux . Vars ( r )
queryParams := r . URL . Query ( )
period , ok := segmentParams [ "period" ]
if ! ok {
payout . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
id := queryParams . Get ( "id" )
if id == "" {
payStubs , err := payout . service . AllPayStubsMonthly ( ctx , period )
if err != nil {
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
} else {
satelliteID , err := storj . NodeIDFromString ( id )
if err != nil {
payout . serveJSONError ( w , http . StatusBadRequest , ErrPayoutAPI . Wrap ( err ) )
return
}
payStub , err := payout . service . SatellitePayStubMonthly ( ctx , satelliteID , period )
if err != nil {
if payouts . ErrNoPayStubForPeriod . Has ( err ) {
payout . serveJSONError ( w , http . StatusNotFound , ErrPayoutAPI . Wrap ( err ) )
return
}
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
2021-02-18 19:59:39 +00:00
if err := json . NewEncoder ( w ) . Encode ( payStub ) ; err != nil {
2021-01-14 16:41:36 +00:00
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
}
}
// PayStubPeriod retrieves paystubs for selected range of months from storagenode database for all satellites or specified satellite by query parameter id.
func ( payout * Payout ) PayStubPeriod ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
segmentParams := mux . Vars ( r )
queryParams := r . URL . Query ( )
start , ok := segmentParams [ "start" ]
if ! ok {
payout . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
end , ok := segmentParams [ "end" ]
if ! ok {
payout . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
id := queryParams . Get ( "id" )
if id == "" {
payStubs , err := payout . service . AllPayStubsPeriod ( ctx , start , end )
if err != nil {
if payouts . ErrBadPeriod . Has ( err ) {
payout . serveJSONError ( w , http . StatusBadRequest , ErrPayoutAPI . Wrap ( err ) )
return
}
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
} else {
satelliteID , err := storj . NodeIDFromString ( id )
if err != nil {
payout . serveJSONError ( w , http . StatusBadRequest , ErrPayoutAPI . Wrap ( err ) )
return
}
payStubs , err := payout . service . SatellitePayStubPeriod ( ctx , satelliteID , start , end )
if err != nil {
if payouts . ErrBadPeriod . Has ( err ) {
payout . serveJSONError ( w , http . StatusBadRequest , ErrPayoutAPI . Wrap ( err ) )
return
}
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
}
}
// HeldHistory returns held amount for each % period for all satellites.
func ( payout * Payout ) HeldHistory ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
heldbackHistory , err := payout . service . AllHeldbackHistory ( ctx )
if err != nil {
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( heldbackHistory ) ; err != nil {
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
}
// PayoutHistory retrieves paystubs for specific period from all satellites and transaction receipts if exists.
func ( payout * Payout ) PayoutHistory ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
segmentParams := mux . Vars ( r )
period , ok := segmentParams [ "period" ]
if ! ok {
payout . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
payoutHistory , err := payout . service . AllSatellitesPayoutPeriod ( ctx , period )
if err != nil {
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payoutHistory ) ; err != nil {
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
}
// HeldAmountPeriods retrieves all periods in which we have some payouts data.
// Have optional parameter - satelliteID.
// If satelliteID specified - will retrieve periods only for concrete satellite.
func ( payout * Payout ) HeldAmountPeriods ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
queryParams := r . URL . Query ( )
id := queryParams . Get ( "id" )
if id == "" {
payStubs , err := payout . service . AllPeriods ( ctx )
if err != nil {
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
} else {
satelliteID , err := storj . NodeIDFromString ( id )
if err != nil {
payout . serveJSONError ( w , http . StatusBadRequest , ErrPayoutAPI . Wrap ( err ) )
return
}
payStubs , err := payout . service . SatellitePeriods ( ctx , satelliteID )
if err != nil {
payout . serveJSONError ( w , http . StatusInternalServerError , ErrPayoutAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
payout . log . Error ( "failed to encode json response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
}
}
// serveJSONError writes JSON error to response output stream.
func ( payout * Payout ) 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 {
payout . log . Error ( "failed to write json error response" , zap . Error ( ErrPayoutAPI . Wrap ( err ) ) )
return
}
}