github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/tequilapi/contract/session.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package contract
    19  
    20  import (
    21  	"math/big"
    22  	"net/http"
    23  	"time"
    24  
    25  	"github.com/go-openapi/strfmt"
    26  	"github.com/mysteriumnetwork/go-rest/apierror"
    27  	"github.com/mysteriumnetwork/node/consumer/session"
    28  	"github.com/mysteriumnetwork/node/identity"
    29  	"github.com/mysteriumnetwork/node/tequilapi/utils"
    30  )
    31  
    32  // NewSessionQuery creates session query with default values.
    33  func NewSessionQuery() SessionQuery {
    34  	return SessionQuery{}
    35  }
    36  
    37  // SessionQuery allows to filter requested sessions.
    38  // swagger:parameters sessionStatsAggregated sessionStatsDaily
    39  type SessionQuery struct {
    40  	// Filter the sessions from this date. Formatted in RFC3339 e.g. 2020-07-01.
    41  	// in: query
    42  	DateFrom *strfmt.Date `json:"date_from"`
    43  
    44  	// Filter the sessions until this date. Formatted in RFC3339 e.g. 2020-07-30.
    45  	// in: query
    46  	DateTo *strfmt.Date `json:"date_to"`
    47  
    48  	// Direction to filter the sessions by. Possible values are "Provided", "Consumed".
    49  	// in: query
    50  	Direction *string `json:"direction"`
    51  
    52  	// Consumer identity to filter the sessions by.
    53  	// in: query
    54  	ConsumerID *string `json:"consumer_id"`
    55  
    56  	// Hermes ID to filter the sessions by.
    57  	// in: query
    58  	HermesID *string `json:"hermes_id"`
    59  
    60  	// Provider identity to filter the sessions by.
    61  	// in: query
    62  	ProviderID *string `json:"provider_id"`
    63  
    64  	// Service type to filter the sessions by.
    65  	// in: query
    66  	ServiceType *string `json:"service_type"`
    67  
    68  	// Status to filter the sessions by. Possible values are "New", "Completed".
    69  	// in: query
    70  	Status *string `json:"status"`
    71  }
    72  
    73  // Bind creates and validates query from API request.
    74  func (q *SessionQuery) Bind(request *http.Request) *apierror.APIError {
    75  	v := apierror.NewValidator()
    76  
    77  	qs := request.URL.Query()
    78  	if qStr := qs.Get("date_from"); qStr != "" {
    79  		if qVal, err := parseDate(qStr); err != nil {
    80  			v.Invalid("date_from", "Cannot parse 'date_from'")
    81  		} else {
    82  			q.DateFrom = qVal
    83  		}
    84  	}
    85  	if qStr := qs.Get("date_to"); qStr != "" {
    86  		if qVal, err := parseDate(qStr); err != nil {
    87  			v.Invalid("date_to", "Cannot parse 'date_to'")
    88  		} else {
    89  			q.DateTo = qVal
    90  		}
    91  	}
    92  	if qStr := qs.Get("direction"); qStr != "" {
    93  		q.Direction = &qStr
    94  	}
    95  	if qStr := qs.Get("consumer_id"); qStr != "" {
    96  		q.ConsumerID = &qStr
    97  	}
    98  	if qStr := qs.Get("hermes_id"); qStr != "" {
    99  		q.HermesID = &qStr
   100  	}
   101  	if qStr := qs.Get("provider_id"); qStr != "" {
   102  		q.ProviderID = &qStr
   103  	}
   104  	if qStr := qs.Get("service_type"); qStr != "" {
   105  		q.ServiceType = &qStr
   106  	}
   107  	if qStr := qs.Get("status"); qStr != "" {
   108  		q.Status = &qStr
   109  	}
   110  
   111  	return v.Err()
   112  }
   113  
   114  // ToFilter converts API query to storage filter.
   115  func (q *SessionQuery) ToFilter() *session.Filter {
   116  	filter := session.NewFilter()
   117  	if q.DateFrom != nil {
   118  		filter.SetStartedFrom(time.Time(*q.DateFrom).Truncate(24 * time.Hour))
   119  	}
   120  	if q.DateTo != nil {
   121  		filter.SetStartedTo(time.Time(*q.DateTo).Truncate(24 * time.Hour).Add(23 * time.Hour).Add(59 * time.Minute).Add(59 * time.Second))
   122  	}
   123  	if q.Direction != nil {
   124  		filter.SetDirection(*q.Direction)
   125  	}
   126  	if q.ConsumerID != nil {
   127  		filter.SetConsumerID(identity.FromAddress(*q.ConsumerID))
   128  	}
   129  	if q.HermesID != nil {
   130  		filter.SetHermesID(*q.HermesID)
   131  	}
   132  	if q.ProviderID != nil {
   133  		filter.SetProviderID(identity.FromAddress(*q.ProviderID))
   134  	}
   135  	if q.ServiceType != nil {
   136  		filter.SetServiceType(*q.ServiceType)
   137  	}
   138  	if q.Status != nil {
   139  		filter.SetStatus(*q.Status)
   140  	}
   141  	return filter
   142  }
   143  
   144  // NewSessionListQuery creates session list with default values.
   145  func NewSessionListQuery() SessionListQuery {
   146  	return SessionListQuery{
   147  		PaginationQuery: NewPaginationQuery(),
   148  	}
   149  }
   150  
   151  // SessionListQuery allows to filter requested sessions.
   152  // swagger:parameters sessionList
   153  type SessionListQuery struct {
   154  	PaginationQuery
   155  	SessionQuery
   156  }
   157  
   158  // Bind creates and validates query from API request.
   159  func (q *SessionListQuery) Bind(request *http.Request) *apierror.APIError {
   160  	v := apierror.NewValidator()
   161  	if err := q.PaginationQuery.Bind(request); err != nil {
   162  		for field, fieldErr := range err.Err.Fields {
   163  			v.Fail(field, fieldErr.Code, fieldErr.Message)
   164  		}
   165  	}
   166  	if err := q.SessionQuery.Bind(request); err != nil {
   167  		for field, fieldErr := range err.Err.Fields {
   168  			v.Fail(field, fieldErr.Code, fieldErr.Message)
   169  		}
   170  	}
   171  	return v.Err()
   172  }
   173  
   174  // NewSessionListResponse maps to API session list.
   175  func NewSessionListResponse(sessions []session.History, paginator *utils.Paginator) SessionListResponse {
   176  	dtoArray := make([]SessionDTO, len(sessions))
   177  	for i, se := range sessions {
   178  		dtoArray[i] = NewSessionDTO(se)
   179  	}
   180  
   181  	return SessionListResponse{
   182  		Items:       dtoArray,
   183  		PageableDTO: NewPageableDTO(paginator),
   184  	}
   185  }
   186  
   187  // SessionListResponse defines session list representable as json.
   188  // swagger:model SessionListResponse
   189  type SessionListResponse struct {
   190  	Items []SessionDTO `json:"items"`
   191  	PageableDTO
   192  }
   193  
   194  // NewSessionStatsAggregatedResponse maps to API aggregated stats.
   195  func NewSessionStatsAggregatedResponse(stats session.Stats) SessionStatsAggregatedResponse {
   196  	return SessionStatsAggregatedResponse{
   197  		Stats: NewSessionStatsDTO(stats),
   198  	}
   199  }
   200  
   201  // SessionStatsAggregatedResponse defines aggregated sessions stats response as json.
   202  // swagger:model SessionStatsAggregatedResponse
   203  type SessionStatsAggregatedResponse struct {
   204  	Stats SessionStatsDTO `json:"stats"`
   205  }
   206  
   207  // NewSessionStatsDailyResponse maps to API session stats grouped by day.
   208  func NewSessionStatsDailyResponse(stats session.Stats, statsDaily map[time.Time]session.Stats) SessionStatsDailyResponse {
   209  	dtoMap := make(map[string]SessionStatsDTO, len(statsDaily))
   210  	for date, stats := range statsDaily {
   211  		dtoMap[date.Format("2006-01-02")] = NewSessionStatsDTO(stats)
   212  	}
   213  
   214  	return SessionStatsDailyResponse{
   215  		Items: dtoMap,
   216  		Stats: NewSessionStatsDTO(stats),
   217  	}
   218  }
   219  
   220  // SessionStatsDailyResponse defines session stats representable as json.
   221  // swagger:model SessionStatsDailyResponse
   222  type SessionStatsDailyResponse struct {
   223  	Items map[string]SessionStatsDTO `json:"items"`
   224  	Stats SessionStatsDTO            `json:"stats"`
   225  }
   226  
   227  // NewSessionStatsDTO maps to API session stats.
   228  func NewSessionStatsDTO(stats session.Stats) SessionStatsDTO {
   229  	return SessionStatsDTO{
   230  		Count:            stats.Count,
   231  		CountConsumers:   len(stats.ConsumerCounts),
   232  		SumBytesReceived: stats.SumDataReceived,
   233  		SumBytesSent:     stats.SumDataSent,
   234  		SumDuration:      uint64(stats.SumDuration.Seconds()),
   235  		SumTokens:        stats.SumTokens,
   236  	}
   237  }
   238  
   239  // SessionStatsDTO represents the session aggregated statistics.
   240  // swagger:model SessionStatsDTO
   241  type SessionStatsDTO struct {
   242  	Count            int      `json:"count"`
   243  	CountConsumers   int      `json:"count_consumers"`
   244  	SumBytesReceived uint64   `json:"sum_bytes_received"`
   245  	SumBytesSent     uint64   `json:"sum_bytes_sent"`
   246  	SumDuration      uint64   `json:"sum_duration"`
   247  	SumTokens        *big.Int `json:"sum_tokens"`
   248  }
   249  
   250  // NewSessionDTO maps to API session.
   251  func NewSessionDTO(se session.History) SessionDTO {
   252  	return SessionDTO{
   253  		ID:              string(se.SessionID),
   254  		Direction:       se.Direction,
   255  		ConsumerID:      se.ConsumerID.Address,
   256  		HermesID:        se.HermesID,
   257  		ProviderID:      se.ProviderID.Address,
   258  		ServiceType:     se.ServiceType,
   259  		ConsumerCountry: se.ConsumerCountry,
   260  		ProviderCountry: se.ProviderCountry,
   261  		CreatedAt:       se.Started.Format(time.RFC3339),
   262  		BytesReceived:   se.DataReceived,
   263  		BytesSent:       se.DataSent,
   264  		Duration:        uint64(se.GetDuration().Seconds()),
   265  		Tokens:          se.Tokens,
   266  		Status:          se.Status,
   267  		IPType:          se.IPType,
   268  	}
   269  }
   270  
   271  // SessionDTO represents the session object.
   272  // swagger:model SessionDTO
   273  type SessionDTO struct {
   274  	// example: 4cfb0324-daf6-4ad8-448b-e61fe0a1f918
   275  	ID string `json:"id"`
   276  
   277  	// example: Consumed
   278  	Direction string `json:"direction"`
   279  
   280  	// example: 0x0000000000000000000000000000000000000001
   281  	ConsumerID string `json:"consumer_id"`
   282  
   283  	// example: 0x0000000000000000000000000000000000000001
   284  	HermesID string `json:"hermes_id"`
   285  
   286  	// example: 0x0000000000000000000000000000000000000001
   287  	ProviderID string `json:"provider_id"`
   288  
   289  	// example: openvpn
   290  	ServiceType string `json:"service_type"`
   291  
   292  	// example: NL
   293  	ConsumerCountry string `json:"consumer_country"`
   294  
   295  	// example: US
   296  	ProviderCountry string `json:"provider_country"`
   297  
   298  	// example: 2019-06-06T11:04:43.910035Z
   299  	CreatedAt string `json:"created_at"`
   300  
   301  	// duration in seconds
   302  	// example: 120
   303  	Duration uint64 `json:"duration"`
   304  
   305  	// example: 1024
   306  	BytesReceived uint64 `json:"bytes_received"`
   307  
   308  	// example: 1024
   309  	BytesSent uint64 `json:"bytes_sent"`
   310  
   311  	// example: 500000
   312  	Tokens *big.Int `json:"tokens"`
   313  
   314  	// example: Completed
   315  	Status string `json:"status"`
   316  
   317  	// example: residential
   318  	IPType string `json:"ip_type"`
   319  }