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

     1  /*
     2   * Copyright (C) 2018 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 endpoints
    19  
    20  import (
    21  	"time"
    22  
    23  	"github.com/gin-gonic/gin"
    24  	"github.com/go-openapi/strfmt"
    25  	"github.com/go-openapi/strfmt/conv"
    26  	"github.com/mysteriumnetwork/go-rest/apierror"
    27  	"github.com/mysteriumnetwork/node/consumer/session"
    28  	"github.com/mysteriumnetwork/node/tequilapi/contract"
    29  	"github.com/mysteriumnetwork/node/tequilapi/utils"
    30  	"github.com/vcraescu/go-paginator/adapter"
    31  )
    32  
    33  type sessionStorage interface {
    34  	List(*session.Filter) ([]session.History, error)
    35  	Stats(*session.Filter) (session.Stats, error)
    36  	StatsByDay(*session.Filter) (map[time.Time]session.Stats, error)
    37  }
    38  
    39  type sessionsEndpoint struct {
    40  	sessionStorage sessionStorage
    41  }
    42  
    43  // NewSessionsEndpoint creates and returns sessions endpoint
    44  func NewSessionsEndpoint(sessionStorage sessionStorage) *sessionsEndpoint {
    45  	return &sessionsEndpoint{
    46  		sessionStorage: sessionStorage,
    47  	}
    48  }
    49  
    50  // swagger:operation GET /sessions Session sessionList
    51  //
    52  //	---
    53  //	summary: Returns sessions history
    54  //	description: Returns list of sessions history filtered by given query
    55  //	responses:
    56  //	  200:
    57  //	    description: List of sessions
    58  //	    schema:
    59  //	      "$ref": "#/definitions/SessionListResponse"
    60  //	  400:
    61  //	    description: Failed to parse or request validation failed
    62  //	    schema:
    63  //	      "$ref": "#/definitions/APIError"
    64  //	  500:
    65  //	    description: Internal server error
    66  //	    schema:
    67  //	      "$ref": "#/definitions/APIError"
    68  func (endpoint *sessionsEndpoint) List(c *gin.Context) {
    69  	query := contract.NewSessionListQuery()
    70  	if err := query.Bind(c.Request); err != nil {
    71  		c.Error(err)
    72  		return
    73  	}
    74  
    75  	sessionsAll, err := endpoint.sessionStorage.List(query.ToFilter())
    76  	if err != nil {
    77  		c.Error(apierror.Internal("Could not list sessions: "+err.Error(), contract.ErrCodeSessionList))
    78  		return
    79  	}
    80  
    81  	var sessions []session.History
    82  	p := utils.NewPaginator(adapter.NewSliceAdapter(sessionsAll), query.PageSize, query.Page)
    83  	if err := p.Results(&sessions); err != nil {
    84  		c.Error(apierror.Internal("Could not paginate sessions: "+err.Error(), contract.ErrCodeSessionListPaginate))
    85  		return
    86  	}
    87  
    88  	sessionsDTO := contract.NewSessionListResponse(sessions, p)
    89  	utils.WriteAsJSON(sessionsDTO, c.Writer)
    90  }
    91  
    92  // swagger:operation GET /sessions/stats-aggregated Session sessionStatsAggregated
    93  //
    94  //	---
    95  //	summary: Returns sessions stats
    96  //	description: Returns aggregated statistics of sessions filtered by given query
    97  //	responses:
    98  //	  200:
    99  //	    description: Session statistics
   100  //	    schema:
   101  //	      "$ref": "#/definitions/SessionStatsAggregatedResponse"
   102  //	  400:
   103  //	    description: Failed to parse or request validation failed
   104  //	    schema:
   105  //	      "$ref": "#/definitions/APIError"
   106  //	  500:
   107  //	    description: Internal server error
   108  //	    schema:
   109  //	      "$ref": "#/definitions/APIError"
   110  func (endpoint *sessionsEndpoint) StatsAggregated(c *gin.Context) {
   111  	query := contract.NewSessionQuery()
   112  	if err := query.Bind(c.Request); err != nil {
   113  		c.Error(err)
   114  		return
   115  	}
   116  
   117  	stats, err := endpoint.sessionStorage.Stats(query.ToFilter())
   118  	if err != nil {
   119  		c.Error(apierror.Internal("Could not list stats: "+err.Error(), contract.ErrCodeSessionStats))
   120  		return
   121  	}
   122  
   123  	sessionsDTO := contract.NewSessionStatsAggregatedResponse(stats)
   124  	utils.WriteAsJSON(sessionsDTO, c.Writer)
   125  }
   126  
   127  // swagger:operation GET /sessions/stats-daily Session sessionStatsDaily
   128  //
   129  //	---
   130  //	summary: Returns sessions stats
   131  //	description: Returns aggregated daily statistics of sessions filtered by given query (date_from=<now -30d> and date_to=<now> by default)
   132  //	responses:
   133  //	  200:
   134  //	    description: Daily session statistics
   135  //	    schema:
   136  //	      "$ref": "#/definitions/SessionStatsDTO"
   137  //	  400:
   138  //	    description: Failed to parse or request validation failed
   139  //	    schema:
   140  //	      "$ref": "#/definitions/APIError"
   141  //	  500:
   142  //	    description: Internal server error
   143  //	    schema:
   144  //	      "$ref": "#/definitions/APIError"
   145  func (endpoint *sessionsEndpoint) StatsDaily(c *gin.Context) {
   146  	query := contract.SessionQuery{
   147  		DateFrom: conv.Date(strfmt.Date(time.Now().UTC().AddDate(0, 0, -30))),
   148  		DateTo:   conv.Date(strfmt.Date(time.Now().UTC())),
   149  	}
   150  	if err := query.Bind(c.Request); err != nil {
   151  		c.Error(err)
   152  		return
   153  	}
   154  
   155  	filter := query.ToFilter()
   156  	stats, err := endpoint.sessionStorage.Stats(filter)
   157  	if err != nil {
   158  		c.Error(apierror.Internal("Could not list stats: "+err.Error(), contract.ErrCodeSessionStats))
   159  		return
   160  	}
   161  
   162  	statsDaily, err := endpoint.sessionStorage.StatsByDay(filter)
   163  	if err != nil {
   164  		c.Error(apierror.Internal("Could not list daily stats: "+err.Error(), contract.ErrCodeSessionStatsDaily))
   165  		return
   166  	}
   167  
   168  	sessionsDTO := contract.NewSessionStatsDailyResponse(stats, statsDaily)
   169  	utils.WriteAsJSON(sessionsDTO, c.Writer)
   170  }
   171  
   172  // AddRoutesForSessions attaches sessions endpoints to router
   173  func AddRoutesForSessions(sessionStorage sessionStorage) func(*gin.Engine) error {
   174  	sessionsEndpoint := NewSessionsEndpoint(sessionStorage)
   175  	return func(e *gin.Engine) error {
   176  		g := e.Group("/sessions")
   177  		{
   178  			g.GET("", sessionsEndpoint.List)
   179  			g.GET("/stats-aggregated", sessionsEndpoint.StatsAggregated)
   180  			g.GET("/stats-daily", sessionsEndpoint.StatsDaily)
   181  		}
   182  		return nil
   183  	}
   184  }