2020-03-15 18:30:23 +00:00
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package consoleapi
import (
"encoding/json"
"net/http"
2020-03-16 01:32:52 +00:00
"github.com/gorilla/mux"
2020-03-15 18:30:23 +00:00
"github.com/zeebo/errs"
"go.uber.org/zap"
"storj.io/storj/pkg/storj"
"storj.io/storj/storagenode/heldamount"
)
2020-03-26 14:53:15 +00:00
// ErrHeldAmountAPI - console heldAmount api error type.
var ErrHeldAmountAPI = errs . Class ( "heldAmount console web error" )
2020-03-15 18:30:23 +00:00
// HeldAmount is an api controller that exposes all held amount related api.
type HeldAmount struct {
service * heldamount . Service
log * zap . Logger
}
// NewHeldAmount is a constructor for heldAmount controller.
func NewHeldAmount ( log * zap . Logger , service * heldamount . Service ) * HeldAmount {
return & HeldAmount {
log : log ,
service : service ,
}
}
2020-03-26 14:53:15 +00:00
// PayStubMonthly returns heldamount, storage holding and prices data for specific month from all satellites or specified satellite by query parameter id.
func ( heldAmount * HeldAmount ) PayStubMonthly ( w http . ResponseWriter , r * http . Request ) {
2020-03-15 18:30:23 +00:00
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
2020-03-26 14:53:15 +00:00
segmentParams := mux . Vars ( r )
queryParams := r . URL . Query ( )
2020-03-16 04:28:03 +00:00
2020-03-26 14:53:15 +00:00
period , ok := segmentParams [ "period" ]
2020-03-16 04:28:03 +00:00
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
2020-03-26 14:53:15 +00:00
id := queryParams . Get ( "id" )
if id == "" {
payStubs , err := heldAmount . service . AllPayStubsMonthlyCached ( ctx , period )
if err != nil {
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
return
}
} else {
satelliteID , err := storj . NodeIDFromString ( id )
if err != nil {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrHeldAmountAPI . Wrap ( err ) )
return
}
payStub , err := heldAmount . service . SatellitePayStubMonthlyCached ( ctx , satelliteID , period )
if err != nil {
if heldamount . ErrNoPayStubForPeriod . Has ( err ) {
heldAmount . serveJSONError ( w , http . StatusNotFound , ErrHeldAmountAPI . Wrap ( err ) )
return
}
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStub ) ; err != nil {
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
return
}
2020-03-16 04:28:03 +00:00
}
}
2020-03-26 14:53:15 +00:00
// PayStubPeriod retrieves held amount for selected range of months from storagenode database for all satellites or specified satellite by query parameter id.
func ( heldAmount * HeldAmount ) PayStubPeriod ( w http . ResponseWriter , r * http . Request ) {
2020-03-16 04:28:03 +00:00
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
2020-03-26 14:53:15 +00:00
segmentParams := mux . Vars ( r )
queryParams := r . URL . Query ( )
2020-03-16 04:28:03 +00:00
2020-03-26 14:53:15 +00:00
start , ok := segmentParams [ "start" ]
2020-03-16 04:28:03 +00:00
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
2020-03-26 14:53:15 +00:00
end , ok := segmentParams [ "end" ]
2020-03-16 04:28:03 +00:00
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
2020-03-26 14:53:15 +00:00
id := queryParams . Get ( "id" )
if id == "" {
payStubs , err := heldAmount . service . AllPayStubsPeriodCached ( ctx , start , end )
if err != nil {
if heldamount . ErrBadPeriod . Has ( err ) {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrHeldAmountAPI . Wrap ( err ) )
return
}
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
return
}
} else {
satelliteID , err := storj . NodeIDFromString ( id )
if err != nil {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrHeldAmountAPI . Wrap ( err ) )
return
}
payStubs , err := heldAmount . service . SatellitePayStubPeriodCached ( ctx , satelliteID , start , end )
if err != nil {
if heldamount . ErrBadPeriod . Has ( err ) {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrHeldAmountAPI . Wrap ( err ) )
return
}
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
return
}
2020-03-16 04:28:03 +00:00
}
}
2020-03-18 11:27:42 +00:00
// SatellitePaymentMonthly returns payment data from satellite for specific month.
func ( heldAmount * HeldAmount ) SatellitePaymentMonthly ( w http . ResponseWriter , r * http . Request ) {
2020-03-15 18:30:23 +00:00
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
2020-03-16 01:32:52 +00:00
params := mux . Vars ( r )
2020-03-15 18:30:23 +00:00
2020-03-16 01:32:52 +00:00
period , ok := params [ "period" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
id , ok := params [ "satelliteID" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
2020-03-15 18:30:23 +00:00
satelliteID , err := storj . NodeIDFromString ( id )
if err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrHeldAmountAPI . Wrap ( err ) )
2020-03-15 18:30:23 +00:00
return
}
2020-03-18 11:27:42 +00:00
paymentData , err := heldAmount . service . SatellitePaymentMonthlyCached ( ctx , satelliteID , period )
2020-03-15 18:30:23 +00:00
if err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
2020-03-15 18:30:23 +00:00
return
}
if err := json . NewEncoder ( w ) . Encode ( paymentData ) ; err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
2020-03-15 18:30:23 +00:00
return
}
}
2020-03-18 11:27:42 +00:00
// AllPaymentsMonthly returns payments for specific month from all satellites.
func ( heldAmount * HeldAmount ) AllPaymentsMonthly ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
params := mux . Vars ( r )
period , ok := params [ "period" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
payStubs , err := heldAmount . service . AllPaymentsMonthlyCached ( ctx , period )
if err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
2020-03-18 11:27:42 +00:00
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
2020-03-18 11:27:42 +00:00
return
}
}
// SatellitePaymentPeriod retrieves payment for selected satellite for selected period from storagenode database.
func ( heldAmount * HeldAmount ) SatellitePaymentPeriod ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
params := mux . Vars ( r )
id , ok := params [ "satelliteID" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
satelliteID , err := storj . NodeIDFromString ( id )
if err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrHeldAmountAPI . Wrap ( err ) )
2020-03-18 11:27:42 +00:00
return
}
start , ok := params [ "start" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
end , ok := params [ "end" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
payments , err := heldAmount . service . SatellitePaymentPeriodCached ( ctx , satelliteID , start , end )
if err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
2020-03-18 11:27:42 +00:00
return
}
if err := json . NewEncoder ( w ) . Encode ( payments ) ; err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
2020-03-18 11:27:42 +00:00
return
}
}
// AllPaymentsPeriod retrieves payment for all satellites for selected range of months from storagenode database.
func ( heldAmount * HeldAmount ) AllPaymentsPeriod ( w http . ResponseWriter , r * http . Request ) {
ctx := r . Context ( )
var err error
defer mon . Task ( ) ( & ctx ) ( & err )
w . Header ( ) . Set ( contentType , applicationJSON )
params := mux . Vars ( r )
start , ok := params [ "start" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
end , ok := params [ "end" ]
if ! ok {
heldAmount . serveJSONError ( w , http . StatusBadRequest , ErrNotificationsAPI . Wrap ( err ) )
return
}
payStubs , err := heldAmount . service . AllPaymentsPeriodCached ( ctx , start , end )
if err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . serveJSONError ( w , http . StatusInternalServerError , ErrHeldAmountAPI . Wrap ( err ) )
2020-03-18 11:27:42 +00:00
return
}
if err := json . NewEncoder ( w ) . Encode ( payStubs ) ; err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . log . Error ( "failed to encode json response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
2020-03-18 11:27:42 +00:00
return
}
}
2020-03-15 18:30:23 +00:00
// serveJSONError writes JSON error to response output stream.
2020-03-16 01:32:52 +00:00
func ( heldAmount * HeldAmount ) serveJSONError ( w http . ResponseWriter , status int , err error ) {
2020-03-15 18:30:23 +00:00
w . WriteHeader ( status )
var response struct {
Error string ` json:"error" `
}
response . Error = err . Error ( )
err = json . NewEncoder ( w ) . Encode ( response )
if err != nil {
2020-03-26 14:53:15 +00:00
heldAmount . log . Error ( "failed to write json error response" , zap . Error ( ErrHeldAmountAPI . Wrap ( err ) ) )
2020-03-15 18:30:23 +00:00
return
}
}