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 }