diff --git a/cmd/internal/openapi/client.gen.go b/cmd/internal/openapi/client.gen.go index b830abd7..822d275b 100644 --- a/cmd/internal/openapi/client.gen.go +++ b/cmd/internal/openapi/client.gen.go @@ -1354,440 +1354,6 @@ type ActivityPage struct { Total int `json:"total"` } -// AdminCoreStats defines model for AdminCoreStats. -type AdminCoreStats struct { - GeneratedAt string `json:"generatedAt"` - Operations struct { - FailedBackgroundJobs int `json:"failedBackgroundJobs"` - OfflineDownloaders int `json:"offlineDownloaders"` - PendingInvitations int `json:"pendingInvitations"` - RunningDownloadTasks int `json:"runningDownloadTasks"` - } `json:"operations"` - Sharing struct { - ActiveShares int `json:"activeShares"` - Downloads int `json:"downloads"` - TotalShares int `json:"totalShares"` - Views int `json:"views"` - } `json:"sharing"` - Spaces struct { - NewLast30Days int `json:"newLast30Days"` - Personal int `json:"personal"` - Team int `json:"team"` - Total int `json:"total"` - } `json:"spaces"` - Storage struct { - ActiveBackendCount int `json:"activeBackendCount"` - BackendCount int `json:"backendCount"` - CapacityBytes int `json:"capacityBytes"` - QuotaBytes int `json:"quotaBytes"` - QuotaUtilization float32 `json:"quotaUtilization"` - UsedBytes int `json:"usedBytes"` - } `json:"storage"` - Traffic struct { - Period string `json:"period"` - QuotaBytes int `json:"quotaBytes"` - UsedBytes int `json:"usedBytes"` - Utilization float32 `json:"utilization"` - } `json:"traffic"` - Users struct { - ActiveLast30Days int `json:"activeLast30Days"` - Admins int `json:"admins"` - NewLast7Days int `json:"newLast7Days"` - Total int `json:"total"` - } `json:"users"` -} - -// AdminDashboardGrowthStats defines model for AdminDashboardGrowthStats. -type AdminDashboardGrowthStats struct { - ActiveUserTrend []struct { - Date string `json:"date"` - Dau float32 `json:"dau"` - Mau float32 `json:"mau"` - Wau float32 `json:"wau"` - } `json:"activeUserTrend"` - From string `json:"from"` - GeneratedAt string `json:"generatedAt"` - RegistrationSources []struct { - Name string `json:"name"` - Percent float32 `json:"percent"` - Value float32 `json:"value"` - } `json:"registrationSources"` - Summary struct { - ActiveUsers struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"activeUsers"` - BannedUsers float32 `json:"bannedUsers"` - NewUsers struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"newUsers"` - SilentUsers float32 `json:"silentUsers"` - TotalUsers float32 `json:"totalUsers"` - VerifiedUsers float32 `json:"verifiedUsers"` - } `json:"summary"` - To string `json:"to"` - UserScaleTrend []struct { - Date string `json:"date"` - NewUsers float32 `json:"newUsers"` - TotalUsers float32 `json:"totalUsers"` - } `json:"userScaleTrend"` - UserStatus []struct { - Name string `json:"name"` - Percent float32 `json:"percent"` - Value float32 `json:"value"` - } `json:"userStatus"` -} - -// AdminDashboardOverviewStats defines model for AdminDashboardOverviewStats. -type AdminDashboardOverviewStats struct { - From string `json:"from"` - GeneratedAt string `json:"generatedAt"` - To string `json:"to"` - Totals struct { - ActiveShares float32 `json:"activeShares"` - ActiveUsers struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"activeUsers"` - DownloadBytes struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"downloadBytes"` - NewUsers struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"newUsers"` - ShareDownloads struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"shareDownloads"` - ShareViews struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"shareViews"` - StorageQuotaBytes float32 `json:"storageQuotaBytes"` - StorageUsedBytes float32 `json:"storageUsedBytes"` - TrafficBytes struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"trafficBytes"` - UploadBytes struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"uploadBytes"` - Users float32 `json:"users"` - } `json:"totals"` - Trends []struct { - ActiveUsers float32 `json:"activeUsers"` - Date string `json:"date"` - DownloadBytes float32 `json:"downloadBytes"` - NewUsers float32 `json:"newUsers"` - StorageUsedBytes float32 `json:"storageUsedBytes"` - UploadBytes float32 `json:"uploadBytes"` - } `json:"trends"` -} - -// AdminDashboardRankingStats defines model for AdminDashboardRankingStats. -type AdminDashboardRankingStats struct { - From string `json:"from"` - GeneratedAt string `json:"generatedAt"` - StorageByType []struct { - Bytes float32 `json:"bytes"` - Files float32 `json:"files"` - Type string `json:"type"` - } `json:"storageByType"` - To string `json:"to"` - TopShares []struct { - CreatorId string `json:"creatorId"` - CreatorName string `json:"creatorName"` - DownloadPercent float32 `json:"downloadPercent"` - Downloads float32 `json:"downloads"` - Id string `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Token string `json:"token"` - ViewPercent float32 `json:"viewPercent"` - Views float32 `json:"views"` - } `json:"topShares"` - TopSpaces []struct { - OrgId string `json:"orgId"` - OrgName string `json:"orgName"` - OrgType string `json:"orgType"` - QuotaBytes float32 `json:"quotaBytes"` - UsedBytes float32 `json:"usedBytes"` - Utilization float32 `json:"utilization"` - } `json:"topSpaces"` -} - -// AdminDashboardSharingStats defines model for AdminDashboardSharingStats. -type AdminDashboardSharingStats struct { - From string `json:"from"` - Funnel []struct { - Name string `json:"name"` - Percent float32 `json:"percent"` - Value float32 `json:"value"` - } `json:"funnel"` - GeneratedAt string `json:"generatedAt"` - SourceBreakdown []struct { - Name string `json:"name"` - Percent float32 `json:"percent"` - Value float32 `json:"value"` - } `json:"sourceBreakdown"` - Summary struct { - ActiveShares float32 `json:"activeShares"` - CreatedShares struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"createdShares"` - DownloadConversionRate float32 `json:"downloadConversionRate"` - Downloads struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"downloads"` - Saves struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"saves"` - Views struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"views"` - } `json:"summary"` - To string `json:"to"` - TopShares []struct { - CreatorId string `json:"creatorId"` - CreatorName string `json:"creatorName"` - DownloadPercent float32 `json:"downloadPercent"` - Downloads float32 `json:"downloads"` - Id string `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Token string `json:"token"` - ViewPercent float32 `json:"viewPercent"` - Views float32 `json:"views"` - } `json:"topShares"` - Trend []struct { - Date string `json:"date"` - Downloads float32 `json:"downloads"` - Saves float32 `json:"saves"` - Views float32 `json:"views"` - } `json:"trend"` - TypeBreakdown []struct { - Name string `json:"name"` - Percent float32 `json:"percent"` - Value float32 `json:"value"` - } `json:"typeBreakdown"` -} - -// AdminDashboardStorageStats defines model for AdminDashboardStorageStats. -type AdminDashboardStorageStats struct { - AgeBreakdown []struct { - Bytes float32 `json:"bytes"` - Files float32 `json:"files"` - Name string `json:"name"` - Percent float32 `json:"percent"` - } `json:"ageBreakdown"` - From string `json:"from"` - GeneratedAt string `json:"generatedAt"` - SizeBreakdown []struct { - Bytes float32 `json:"bytes"` - Files float32 `json:"files"` - Name string `json:"name"` - Percent float32 `json:"percent"` - } `json:"sizeBreakdown"` - StorageTrend []struct { - Date string `json:"date"` - NewBytes float32 `json:"newBytes"` - NewFiles float32 `json:"newFiles"` - UsedBytes float32 `json:"usedBytes"` - } `json:"storageTrend"` - Summary struct { - ColdFileBytes float32 `json:"coldFileBytes"` - FileCount float32 `json:"fileCount"` - NewBytes struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"newBytes"` - NewFiles struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"newFiles"` - QuotaBytes float32 `json:"quotaBytes"` - StorageUsedBytes float32 `json:"storageUsedBytes"` - } `json:"summary"` - To string `json:"to"` - TypeBreakdown []struct { - Bytes float32 `json:"bytes"` - Files float32 `json:"files"` - Percent float32 `json:"percent"` - Type string `json:"type"` - } `json:"typeBreakdown"` -} - -// AdminDashboardTrafficStats defines model for AdminDashboardTrafficStats. -type AdminDashboardTrafficStats struct { - BandwidthTrend []struct { - Bytes float32 `json:"bytes"` - Date string `json:"date"` - } `json:"bandwidthTrend"` - FailureReasons []struct { - Name string `json:"name"` - Percent float32 `json:"percent"` - Value float32 `json:"value"` - } `json:"failureReasons"` - From string `json:"from"` - GeneratedAt string `json:"generatedAt"` - IssueStatus []struct { - Count float32 `json:"count"` - Percent float32 `json:"percent"` - Status string `json:"status"` - } `json:"issueStatus"` - SourceBreakdown []struct { - Bytes float32 `json:"bytes"` - Name string `json:"name"` - Percent float32 `json:"percent"` - Requests float32 `json:"requests"` - } `json:"sourceBreakdown"` - SuccessTrend []struct { - Date string `json:"date"` - DownloadSuccessRate float32 `json:"downloadSuccessRate"` - UploadSuccessRate float32 `json:"uploadSuccessRate"` - } `json:"successTrend"` - Summary struct { - BlockedDownloads float32 `json:"blockedDownloads"` - IssueRate float32 `json:"issueRate"` - IssuedDownloads float32 `json:"issuedDownloads"` - PeakDailyBytes float32 `json:"peakDailyBytes"` - RequestCount struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"requestCount"` - TotalBytes struct { - ChangePercent float32 `json:"changePercent"` - PreviousValue float32 `json:"previousValue"` - Value float32 `json:"value"` - } `json:"totalBytes"` - } `json:"summary"` - To string `json:"to"` - TrafficTrend []struct { - Date string `json:"date"` - DownloadBytes float32 `json:"downloadBytes"` - Requests float32 `json:"requests"` - UploadBytes float32 `json:"uploadBytes"` - } `json:"trafficTrend"` -} - -// AdminDetailedStats defines model for AdminDetailedStats. -type AdminDetailedStats struct { - GeneratedAt string `json:"generatedAt"` - PeriodDays int `json:"periodDays"` - Reliability struct { - BackgroundJobs struct { - ByStatus []struct { - Count int `json:"count"` - Status string `json:"status"` - } `json:"byStatus"` - Failed int `json:"failed"` - FailureRate float32 `json:"failureRate"` - Failures []struct { - CreatedAt string `json:"createdAt"` - ErrorMessage *string `json:"errorMessage"` - Id string `json:"id"` - Type string `json:"type"` - } `json:"failures"` - Total int `json:"total"` - } `json:"backgroundJobs"` - CloudTrafficReports struct { - Failed int `json:"failed"` - Pending int `json:"pending"` - } `json:"cloudTrafficReports"` - License struct { - Active bool `json:"active"` - Edition *string `json:"edition"` - LastRefreshAt *string `json:"lastRefreshAt"` - LastRefreshError *string `json:"lastRefreshError"` - } `json:"license"` - } `json:"reliability"` - RemoteDownloads struct { - ByDownloader []struct { - DownloaderId string `json:"downloaderId"` - FailedTasks int `json:"failedTasks"` - LastHeartbeatAt *string `json:"lastHeartbeatAt"` - Name string `json:"name"` - Status string `json:"status"` - Tasks int `json:"tasks"` - } `json:"byDownloader"` - ByStatus []struct { - Count int `json:"count"` - Status string `json:"status"` - } `json:"byStatus"` - Completed int `json:"completed"` - Failed int `json:"failed"` - FailureReasons []struct { - Count int `json:"count"` - Reason string `json:"reason"` - } `json:"failureReasons"` - Running int `json:"running"` - SuccessRate float32 `json:"successRate"` - Total int `json:"total"` - } `json:"remoteDownloads"` - Sharing struct { - ConversionRate float32 `json:"conversionRate"` - DownloadLimitHitShares int `json:"downloadLimitHitShares"` - ExpiredShares int `json:"expiredShares"` - RevokedShares int `json:"revokedShares"` - } `json:"sharing"` - StorageByType []struct { - Bytes int `json:"bytes"` - Files int `json:"files"` - Type string `json:"type"` - } `json:"storageByType"` - TopShares []struct { - CreatorId string `json:"creatorId"` - CreatorName string `json:"creatorName"` - Downloads int `json:"downloads"` - Id string `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Token string `json:"token"` - Views int `json:"views"` - } `json:"topShares"` - Trends []struct { - ActiveUsers int `json:"activeUsers"` - Date string `json:"date"` - FailedJobs int `json:"failedJobs"` - RemoteTasks int `json:"remoteTasks"` - ShareDownloads int `json:"shareDownloads"` - ShareViews int `json:"shareViews"` - Signups int `json:"signups"` - } `json:"trends"` - UsageBySpace []struct { - OrgId string `json:"orgId"` - OrgName string `json:"orgName"` - OrgType string `json:"orgType"` - QuotaBytes int `json:"quotaBytes"` - UsedBytes int `json:"usedBytes"` - Utilization float32 `json:"utilization"` - } `json:"usageBySpace"` -} - // AdminUserQuota defines model for AdminUserQuota. type AdminUserQuota struct { HasPersonalOrg bool `json:"hasPersonalOrg"` @@ -2801,47 +2367,6 @@ type User struct { Username *string `json:"username,omitempty"` } -// GetAdminDetailedStatsParams defines parameters for GetAdminDetailedStats. -type GetAdminDetailedStatsParams struct { - PeriodDays *int `form:"periodDays,omitempty" json:"periodDays,omitempty"` -} - -// GetAdminDashboardGrowthStatsParams defines parameters for GetAdminDashboardGrowthStats. -type GetAdminDashboardGrowthStatsParams struct { - From *string `form:"from,omitempty" json:"from,omitempty"` - To *string `form:"to,omitempty" json:"to,omitempty"` -} - -// GetAdminDashboardOverviewStatsParams defines parameters for GetAdminDashboardOverviewStats. -type GetAdminDashboardOverviewStatsParams struct { - From *string `form:"from,omitempty" json:"from,omitempty"` - To *string `form:"to,omitempty" json:"to,omitempty"` -} - -// GetAdminDashboardRankingStatsParams defines parameters for GetAdminDashboardRankingStats. -type GetAdminDashboardRankingStatsParams struct { - From *string `form:"from,omitempty" json:"from,omitempty"` - To *string `form:"to,omitempty" json:"to,omitempty"` -} - -// GetAdminDashboardSharingStatsParams defines parameters for GetAdminDashboardSharingStats. -type GetAdminDashboardSharingStatsParams struct { - From *string `form:"from,omitempty" json:"from,omitempty"` - To *string `form:"to,omitempty" json:"to,omitempty"` -} - -// GetAdminDashboardStorageStatsParams defines parameters for GetAdminDashboardStorageStats. -type GetAdminDashboardStorageStatsParams struct { - From *string `form:"from,omitempty" json:"from,omitempty"` - To *string `form:"to,omitempty" json:"to,omitempty"` -} - -// GetAdminDashboardTrafficStatsParams defines parameters for GetAdminDashboardTrafficStats. -type GetAdminDashboardTrafficStatsParams struct { - From *string `form:"from,omitempty" json:"from,omitempty"` - To *string `form:"to,omitempty" json:"to,omitempty"` -} - // BanUserJSONBody defines parameters for BanUser. type BanUserJSONBody struct { // BanExpiresIn The number of seconds until the ban expires @@ -4824,30 +4349,6 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption { // The interface specification for the client above. type ClientInterface interface { - // GetAdminCoreStats request - GetAdminCoreStats(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetAdminDetailedStats request - GetAdminDetailedStats(ctx context.Context, params *GetAdminDetailedStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetAdminDashboardGrowthStats request - GetAdminDashboardGrowthStats(ctx context.Context, params *GetAdminDashboardGrowthStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetAdminDashboardOverviewStats request - GetAdminDashboardOverviewStats(ctx context.Context, params *GetAdminDashboardOverviewStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetAdminDashboardRankingStats request - GetAdminDashboardRankingStats(ctx context.Context, params *GetAdminDashboardRankingStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetAdminDashboardSharingStats request - GetAdminDashboardSharingStats(ctx context.Context, params *GetAdminDashboardSharingStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetAdminDashboardStorageStats request - GetAdminDashboardStorageStats(ctx context.Context, params *GetAdminDashboardStorageStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetAdminDashboardTrafficStats request - GetAdminDashboardTrafficStats(ctx context.Context, params *GetAdminDashboardTrafficStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetApiAuthAccountInfo request GetApiAuthAccountInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -5694,102 +5195,6 @@ type ClientInterface interface { ListUserObjects(ctx context.Context, username string, reqEditors ...RequestEditorFn) (*http.Response, error) } -func (c *Client) GetAdminCoreStats(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminCoreStatsRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetAdminDetailedStats(ctx context.Context, params *GetAdminDetailedStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminDetailedStatsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetAdminDashboardGrowthStats(ctx context.Context, params *GetAdminDashboardGrowthStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminDashboardGrowthStatsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetAdminDashboardOverviewStats(ctx context.Context, params *GetAdminDashboardOverviewStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminDashboardOverviewStatsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetAdminDashboardRankingStats(ctx context.Context, params *GetAdminDashboardRankingStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminDashboardRankingStatsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetAdminDashboardSharingStats(ctx context.Context, params *GetAdminDashboardSharingStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminDashboardSharingStatsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetAdminDashboardStorageStats(ctx context.Context, params *GetAdminDashboardStorageStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminDashboardStorageStatsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetAdminDashboardTrafficStats(ctx context.Context, params *GetAdminDashboardTrafficStatsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetAdminDashboardTrafficStatsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - func (c *Client) GetApiAuthAccountInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetApiAuthAccountInfoRequest(c.Server) if err != nil { @@ -9582,483 +8987,6 @@ func (c *Client) ListUserObjects(ctx context.Context, username string, reqEditor return c.Client.Do(req) } -// NewGetAdminCoreStatsRequest generates requests for GetAdminCoreStats -func NewGetAdminCoreStatsRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/core") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetAdminDetailedStatsRequest generates requests for GetAdminDetailedStats -func NewGetAdminDetailedStatsRequest(server string, params *GetAdminDetailedStatsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/details") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - // queryValues collects non-styled parameters (passthrough, JSON) - // that are safe to round-trip through url.Values.Encode(). - queryValues := queryURL.Query() - // rawQueryFragments collects pre-encoded query fragments from - // styled parameters, preserving literal commas as delimiters - // per the OpenAPI spec (e.g. "color=blue,black,brown"). - var rawQueryFragments []string - - if params.PeriodDays != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "periodDays", *params.PeriodDays, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if encoded := queryValues.Encode(); encoded != "" { - rawQueryFragments = append(rawQueryFragments, encoded) - } - queryURL.RawQuery = strings.Join(rawQueryFragments, "&") - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetAdminDashboardGrowthStatsRequest generates requests for GetAdminDashboardGrowthStats -func NewGetAdminDashboardGrowthStatsRequest(server string, params *GetAdminDashboardGrowthStatsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/growth") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - // queryValues collects non-styled parameters (passthrough, JSON) - // that are safe to round-trip through url.Values.Encode(). - queryValues := queryURL.Query() - // rawQueryFragments collects pre-encoded query fragments from - // styled parameters, preserving literal commas as delimiters - // per the OpenAPI spec (e.g. "color=blue,black,brown"). - var rawQueryFragments []string - - if params.From != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "from", *params.From, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if params.To != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "to", *params.To, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if encoded := queryValues.Encode(); encoded != "" { - rawQueryFragments = append(rawQueryFragments, encoded) - } - queryURL.RawQuery = strings.Join(rawQueryFragments, "&") - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetAdminDashboardOverviewStatsRequest generates requests for GetAdminDashboardOverviewStats -func NewGetAdminDashboardOverviewStatsRequest(server string, params *GetAdminDashboardOverviewStatsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/overview") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - // queryValues collects non-styled parameters (passthrough, JSON) - // that are safe to round-trip through url.Values.Encode(). - queryValues := queryURL.Query() - // rawQueryFragments collects pre-encoded query fragments from - // styled parameters, preserving literal commas as delimiters - // per the OpenAPI spec (e.g. "color=blue,black,brown"). - var rawQueryFragments []string - - if params.From != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "from", *params.From, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if params.To != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "to", *params.To, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if encoded := queryValues.Encode(); encoded != "" { - rawQueryFragments = append(rawQueryFragments, encoded) - } - queryURL.RawQuery = strings.Join(rawQueryFragments, "&") - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetAdminDashboardRankingStatsRequest generates requests for GetAdminDashboardRankingStats -func NewGetAdminDashboardRankingStatsRequest(server string, params *GetAdminDashboardRankingStatsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/ranking") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - // queryValues collects non-styled parameters (passthrough, JSON) - // that are safe to round-trip through url.Values.Encode(). - queryValues := queryURL.Query() - // rawQueryFragments collects pre-encoded query fragments from - // styled parameters, preserving literal commas as delimiters - // per the OpenAPI spec (e.g. "color=blue,black,brown"). - var rawQueryFragments []string - - if params.From != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "from", *params.From, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if params.To != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "to", *params.To, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if encoded := queryValues.Encode(); encoded != "" { - rawQueryFragments = append(rawQueryFragments, encoded) - } - queryURL.RawQuery = strings.Join(rawQueryFragments, "&") - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetAdminDashboardSharingStatsRequest generates requests for GetAdminDashboardSharingStats -func NewGetAdminDashboardSharingStatsRequest(server string, params *GetAdminDashboardSharingStatsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/sharing") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - // queryValues collects non-styled parameters (passthrough, JSON) - // that are safe to round-trip through url.Values.Encode(). - queryValues := queryURL.Query() - // rawQueryFragments collects pre-encoded query fragments from - // styled parameters, preserving literal commas as delimiters - // per the OpenAPI spec (e.g. "color=blue,black,brown"). - var rawQueryFragments []string - - if params.From != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "from", *params.From, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if params.To != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "to", *params.To, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if encoded := queryValues.Encode(); encoded != "" { - rawQueryFragments = append(rawQueryFragments, encoded) - } - queryURL.RawQuery = strings.Join(rawQueryFragments, "&") - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetAdminDashboardStorageStatsRequest generates requests for GetAdminDashboardStorageStats -func NewGetAdminDashboardStorageStatsRequest(server string, params *GetAdminDashboardStorageStatsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/storage") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - // queryValues collects non-styled parameters (passthrough, JSON) - // that are safe to round-trip through url.Values.Encode(). - queryValues := queryURL.Query() - // rawQueryFragments collects pre-encoded query fragments from - // styled parameters, preserving literal commas as delimiters - // per the OpenAPI spec (e.g. "color=blue,black,brown"). - var rawQueryFragments []string - - if params.From != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "from", *params.From, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if params.To != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "to", *params.To, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if encoded := queryValues.Encode(); encoded != "" { - rawQueryFragments = append(rawQueryFragments, encoded) - } - queryURL.RawQuery = strings.Join(rawQueryFragments, "&") - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetAdminDashboardTrafficStatsRequest generates requests for GetAdminDashboardTrafficStats -func NewGetAdminDashboardTrafficStatsRequest(server string, params *GetAdminDashboardTrafficStatsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/admin/stats/traffic") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - // queryValues collects non-styled parameters (passthrough, JSON) - // that are safe to round-trip through url.Values.Encode(). - queryValues := queryURL.Query() - // rawQueryFragments collects pre-encoded query fragments from - // styled parameters, preserving literal commas as delimiters - // per the OpenAPI spec (e.g. "color=blue,black,brown"). - var rawQueryFragments []string - - if params.From != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "from", *params.From, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if params.To != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "to", *params.To, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else { - for _, qp := range strings.Split(queryFrag, "&") { - rawQueryFragments = append(rawQueryFragments, qp) - } - } - - } - - if encoded := queryValues.Encode(); encoded != "" { - rawQueryFragments = append(rawQueryFragments, encoded) - } - queryURL.RawQuery = strings.Join(rawQueryFragments, "&") - } - - req, err := http.NewRequest(http.MethodGet, queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - // NewGetApiAuthAccountInfoRequest generates requests for GetApiAuthAccountInfo func NewGetApiAuthAccountInfoRequest(server string) (*http.Request, error) { var err error @@ -19192,30 +18120,6 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // GetAdminCoreStatsWithResponse request - GetAdminCoreStatsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetAdminCoreStatsResponse, error) - - // GetAdminDetailedStatsWithResponse request - GetAdminDetailedStatsWithResponse(ctx context.Context, params *GetAdminDetailedStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDetailedStatsResponse, error) - - // GetAdminDashboardGrowthStatsWithResponse request - GetAdminDashboardGrowthStatsWithResponse(ctx context.Context, params *GetAdminDashboardGrowthStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardGrowthStatsResponse, error) - - // GetAdminDashboardOverviewStatsWithResponse request - GetAdminDashboardOverviewStatsWithResponse(ctx context.Context, params *GetAdminDashboardOverviewStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardOverviewStatsResponse, error) - - // GetAdminDashboardRankingStatsWithResponse request - GetAdminDashboardRankingStatsWithResponse(ctx context.Context, params *GetAdminDashboardRankingStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardRankingStatsResponse, error) - - // GetAdminDashboardSharingStatsWithResponse request - GetAdminDashboardSharingStatsWithResponse(ctx context.Context, params *GetAdminDashboardSharingStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardSharingStatsResponse, error) - - // GetAdminDashboardStorageStatsWithResponse request - GetAdminDashboardStorageStatsWithResponse(ctx context.Context, params *GetAdminDashboardStorageStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardStorageStatsResponse, error) - - // GetAdminDashboardTrafficStatsWithResponse request - GetAdminDashboardTrafficStatsWithResponse(ctx context.Context, params *GetAdminDashboardTrafficStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardTrafficStatsResponse, error) - // GetApiAuthAccountInfoWithResponse request GetApiAuthAccountInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetApiAuthAccountInfoResponse, error) @@ -20062,260 +18966,6 @@ type ClientWithResponsesInterface interface { ListUserObjectsWithResponse(ctx context.Context, username string, reqEditors ...RequestEditorFn) (*ListUserObjectsResponse, error) } -type GetAdminCoreStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminCoreStats - JSON401 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminCoreStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminCoreStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminCoreStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - -type GetAdminDetailedStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminDetailedStats - JSON402 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminDetailedStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminDetailedStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminDetailedStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - -type GetAdminDashboardGrowthStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminDashboardGrowthStats - JSON400 *Error - JSON402 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminDashboardGrowthStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminDashboardGrowthStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminDashboardGrowthStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - -type GetAdminDashboardOverviewStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminDashboardOverviewStats - JSON400 *Error - JSON401 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminDashboardOverviewStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminDashboardOverviewStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminDashboardOverviewStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - -type GetAdminDashboardRankingStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminDashboardRankingStats - JSON400 *Error - JSON402 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminDashboardRankingStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminDashboardRankingStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminDashboardRankingStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - -type GetAdminDashboardSharingStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminDashboardSharingStats - JSON400 *Error - JSON402 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminDashboardSharingStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminDashboardSharingStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminDashboardSharingStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - -type GetAdminDashboardStorageStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminDashboardStorageStats - JSON400 *Error - JSON402 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminDashboardStorageStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminDashboardStorageStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminDashboardStorageStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - -type GetAdminDashboardTrafficStatsResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AdminDashboardTrafficStats - JSON400 *Error - JSON402 *Error -} - -// Status returns HTTPResponse.Status -func (r GetAdminDashboardTrafficStatsResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetAdminDashboardTrafficStatsResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// ContentType is a convenience method to retrieve the Content-Type value from the HTTP response headers -func (r GetAdminDashboardTrafficStatsResponse) ContentType() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Header.Get("Content-Type") - } - return "" -} - type GetApiAuthAccountInfoResponse struct { Body []byte HTTPResponse *http.Response @@ -29051,78 +27701,6 @@ func (r ListUserObjectsResponse) ContentType() string { return "" } -// GetAdminCoreStatsWithResponse request returning *GetAdminCoreStatsResponse -func (c *ClientWithResponses) GetAdminCoreStatsWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetAdminCoreStatsResponse, error) { - rsp, err := c.GetAdminCoreStats(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminCoreStatsResponse(rsp) -} - -// GetAdminDetailedStatsWithResponse request returning *GetAdminDetailedStatsResponse -func (c *ClientWithResponses) GetAdminDetailedStatsWithResponse(ctx context.Context, params *GetAdminDetailedStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDetailedStatsResponse, error) { - rsp, err := c.GetAdminDetailedStats(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminDetailedStatsResponse(rsp) -} - -// GetAdminDashboardGrowthStatsWithResponse request returning *GetAdminDashboardGrowthStatsResponse -func (c *ClientWithResponses) GetAdminDashboardGrowthStatsWithResponse(ctx context.Context, params *GetAdminDashboardGrowthStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardGrowthStatsResponse, error) { - rsp, err := c.GetAdminDashboardGrowthStats(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminDashboardGrowthStatsResponse(rsp) -} - -// GetAdminDashboardOverviewStatsWithResponse request returning *GetAdminDashboardOverviewStatsResponse -func (c *ClientWithResponses) GetAdminDashboardOverviewStatsWithResponse(ctx context.Context, params *GetAdminDashboardOverviewStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardOverviewStatsResponse, error) { - rsp, err := c.GetAdminDashboardOverviewStats(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminDashboardOverviewStatsResponse(rsp) -} - -// GetAdminDashboardRankingStatsWithResponse request returning *GetAdminDashboardRankingStatsResponse -func (c *ClientWithResponses) GetAdminDashboardRankingStatsWithResponse(ctx context.Context, params *GetAdminDashboardRankingStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardRankingStatsResponse, error) { - rsp, err := c.GetAdminDashboardRankingStats(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminDashboardRankingStatsResponse(rsp) -} - -// GetAdminDashboardSharingStatsWithResponse request returning *GetAdminDashboardSharingStatsResponse -func (c *ClientWithResponses) GetAdminDashboardSharingStatsWithResponse(ctx context.Context, params *GetAdminDashboardSharingStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardSharingStatsResponse, error) { - rsp, err := c.GetAdminDashboardSharingStats(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminDashboardSharingStatsResponse(rsp) -} - -// GetAdminDashboardStorageStatsWithResponse request returning *GetAdminDashboardStorageStatsResponse -func (c *ClientWithResponses) GetAdminDashboardStorageStatsWithResponse(ctx context.Context, params *GetAdminDashboardStorageStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardStorageStatsResponse, error) { - rsp, err := c.GetAdminDashboardStorageStats(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminDashboardStorageStatsResponse(rsp) -} - -// GetAdminDashboardTrafficStatsWithResponse request returning *GetAdminDashboardTrafficStatsResponse -func (c *ClientWithResponses) GetAdminDashboardTrafficStatsWithResponse(ctx context.Context, params *GetAdminDashboardTrafficStatsParams, reqEditors ...RequestEditorFn) (*GetAdminDashboardTrafficStatsResponse, error) { - rsp, err := c.GetAdminDashboardTrafficStats(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetAdminDashboardTrafficStatsResponse(rsp) -} - // GetApiAuthAccountInfoWithResponse request returning *GetApiAuthAccountInfoResponse func (c *ClientWithResponses) GetApiAuthAccountInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetApiAuthAccountInfoResponse, error) { rsp, err := c.GetApiAuthAccountInfo(ctx, reqEditors...) @@ -31864,312 +30442,6 @@ func (c *ClientWithResponses) ListUserObjectsWithResponse(ctx context.Context, u return ParseListUserObjectsResponse(rsp) } -// ParseGetAdminCoreStatsResponse parses an HTTP response from a GetAdminCoreStatsWithResponse call -func ParseGetAdminCoreStatsResponse(rsp *http.Response) (*GetAdminCoreStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminCoreStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminCoreStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - } - - return response, nil -} - -// ParseGetAdminDetailedStatsResponse parses an HTTP response from a GetAdminDetailedStatsWithResponse call -func ParseGetAdminDetailedStatsResponse(rsp *http.Response) (*GetAdminDetailedStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminDetailedStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminDetailedStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON402 = &dest - - } - - return response, nil -} - -// ParseGetAdminDashboardGrowthStatsResponse parses an HTTP response from a GetAdminDashboardGrowthStatsWithResponse call -func ParseGetAdminDashboardGrowthStatsResponse(rsp *http.Response) (*GetAdminDashboardGrowthStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminDashboardGrowthStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminDashboardGrowthStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON402 = &dest - - } - - return response, nil -} - -// ParseGetAdminDashboardOverviewStatsResponse parses an HTTP response from a GetAdminDashboardOverviewStatsWithResponse call -func ParseGetAdminDashboardOverviewStatsResponse(rsp *http.Response) (*GetAdminDashboardOverviewStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminDashboardOverviewStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminDashboardOverviewStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - } - - return response, nil -} - -// ParseGetAdminDashboardRankingStatsResponse parses an HTTP response from a GetAdminDashboardRankingStatsWithResponse call -func ParseGetAdminDashboardRankingStatsResponse(rsp *http.Response) (*GetAdminDashboardRankingStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminDashboardRankingStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminDashboardRankingStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON402 = &dest - - } - - return response, nil -} - -// ParseGetAdminDashboardSharingStatsResponse parses an HTTP response from a GetAdminDashboardSharingStatsWithResponse call -func ParseGetAdminDashboardSharingStatsResponse(rsp *http.Response) (*GetAdminDashboardSharingStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminDashboardSharingStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminDashboardSharingStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON402 = &dest - - } - - return response, nil -} - -// ParseGetAdminDashboardStorageStatsResponse parses an HTTP response from a GetAdminDashboardStorageStatsWithResponse call -func ParseGetAdminDashboardStorageStatsResponse(rsp *http.Response) (*GetAdminDashboardStorageStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminDashboardStorageStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminDashboardStorageStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON402 = &dest - - } - - return response, nil -} - -// ParseGetAdminDashboardTrafficStatsResponse parses an HTTP response from a GetAdminDashboardTrafficStatsWithResponse call -func ParseGetAdminDashboardTrafficStatsResponse(rsp *http.Response) (*GetAdminDashboardTrafficStatsResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetAdminDashboardTrafficStatsResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AdminDashboardTrafficStats - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON402 = &dest - - } - - return response, nil -} - // ParseGetApiAuthAccountInfoResponse parses an HTTP response from a GetApiAuthAccountInfoWithResponse call func ParseGetApiAuthAccountInfoResponse(rsp *http.Response) (*GetApiAuthAccountInfoResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/server/adapters/repos/admin-stats.ts b/server/adapters/repos/admin-stats.ts index fb2131c1..aa9f790a 100644 --- a/server/adapters/repos/admin-stats.ts +++ b/server/adapters/repos/admin-stats.ts @@ -24,6 +24,7 @@ import { orgQuotas, shares, siteInvitations, + statsRollupsDaily, storages, webhookEvents, } from '../../db/schema' @@ -38,6 +39,10 @@ import type { const RUNNING_DOWNLOAD_STATUSES = ['queued', 'assigned', 'running', 'downloading', 'ingesting'] const DOWNLOAD_ACTIVITY_ACTIONS = ['share_download', 'object_download'] const AUDITED_DOWNLOAD_SOURCES = new Set(['landing_share', 'object_download']) +const STORAGE_USED_ROLLUP_METRIC = 'storage.used.bytes' +const GLOBAL_ROLLUP_ORG_ID = '' +const GLOBAL_ROLLUP_DIMENSION_KEY = '' +const GLOBAL_ROLLUP_DIMENSION_VALUE = '' export function createAdminStatsRepo(db: Database): AdminStatsRepo { return { @@ -547,7 +552,7 @@ async function getDashboardOverviewStats( const [trendNewUsers, activeByDay, storageUsedByDay, uploadByDay, downloadByDay] = await Promise.all([ getNewUsersByDay(db, range), getActiveUsersByDay(db, range), - getStorageUsedByDay(db, range), + getStorageUsedByDay(db, range, now), getActivityBytesByDay(db, range, ['upload_confirm']), getDownloadBytesByDay(db, range), ]) @@ -651,7 +656,7 @@ async function getDashboardStorageStats( .select({ id: matters.id, type: matters.type, size: matters.size, createdAt: matters.createdAt }) .from(matters) .where(and(eq(matters.status, 'active'), eq(matters.dirtype, 0))), - getStorageUsedByDay(db, range), + getStorageUsedByDay(db, range, now), getStorageByType(db, range), ]) const fileItems = files.map((row) => ({ bytes: row.size ?? 0, createdAt: row.createdAt })) @@ -1083,18 +1088,94 @@ async function getActivityMetadataRows(db: Database, range: AdminStatsDateRange, ) } -async function getStorageUsedByDay(db: Database, range: AdminStatsDateRange): Promise> { +async function getStorageUsedByDay(db: Database, range: AdminStatsDateRange, now: Date): Promise> { + const buckets = createDateBuckets(range) + if (buckets.length === 0) return new Map() + + const firstBucketStart = dateKeyStart(buckets[0]) + const lastBucketStart = dateKeyStart(buckets[buckets.length - 1]) + const rows = await db + .select({ + bucketStart: statsRollupsDaily.bucketStart, + bytes: statsRollupsDaily.bytes, + }) + .from(statsRollupsDaily) + .where( + and( + eq(statsRollupsDaily.metricKey, STORAGE_USED_ROLLUP_METRIC), + eq(statsRollupsDaily.orgId, GLOBAL_ROLLUP_ORG_ID), + eq(statsRollupsDaily.dimensionKey, GLOBAL_ROLLUP_DIMENSION_KEY), + eq(statsRollupsDaily.dimensionValue, GLOBAL_ROLLUP_DIMENSION_VALUE), + gte(statsRollupsDaily.bucketStart, firstBucketStart), + lte(statsRollupsDaily.bucketStart, lastBucketStart), + ), + ) + + const byDay = new Map(rows.map((row) => [dayKey(row.bucketStart), toNumber(row.bytes)])) + const today = dayKey(now) + const missingOrMutableBuckets = buckets.filter((date) => !byDay.has(date) || date === today) + if (missingOrMutableBuckets.length === 0) return byDay + + const computed = await computeStorageUsedByDayFromCurrentFiles(db, missingOrMutableBuckets) + const updatedAt = now + for (const date of missingOrMutableBuckets) { + const bytes = computed.get(date) ?? 0 + byDay.set(date, bytes) + const row = { + id: storageUsedRollupId(date), + bucketStart: dateKeyStart(date), + orgId: GLOBAL_ROLLUP_ORG_ID, + metricKey: STORAGE_USED_ROLLUP_METRIC, + dimensionKey: GLOBAL_ROLLUP_DIMENSION_KEY, + dimensionValue: GLOBAL_ROLLUP_DIMENSION_VALUE, + count: 0, + bytes, + uniqueCount: 0, + metadata: JSON.stringify({ source: 'current_state_backfill' }), + updatedAt, + } + const insert = db.insert(statsRollupsDaily).values(row) + if (date === today) { + await insert.onConflictDoUpdate({ + target: [ + statsRollupsDaily.bucketStart, + statsRollupsDaily.orgId, + statsRollupsDaily.metricKey, + statsRollupsDaily.dimensionKey, + statsRollupsDaily.dimensionValue, + ], + set: { bytes, metadata: row.metadata, updatedAt }, + }) + } else { + await insert.onConflictDoNothing({ + target: [ + statsRollupsDaily.bucketStart, + statsRollupsDaily.orgId, + statsRollupsDaily.metricKey, + statsRollupsDaily.dimensionKey, + statsRollupsDaily.dimensionValue, + ], + }) + } + } + + return byDay +} + +async function computeStorageUsedByDayFromCurrentFiles(db: Database, buckets: string[]): Promise> { + const sortedBuckets = [...buckets].sort() + const lastDayEnd = endOfDateKey(sortedBuckets[sortedBuckets.length - 1]) const files = await db .select({ size: matters.size, createdAt: matters.createdAt }) .from(matters) - .where(and(eq(matters.status, 'active'), eq(matters.dirtype, 0), lte(matters.createdAt, range.to))) + .where(and(eq(matters.status, 'active'), eq(matters.dirtype, 0), lte(matters.createdAt, lastDayEnd))) const sortedFiles = files .map((row) => ({ bytes: row.size ?? 0, createdAt: row.createdAt })) .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()) const byDay = new Map() let cursor = 0 let runningBytes = 0 - for (const date of createDateBuckets(range)) { + for (const date of sortedBuckets) { const dayEnd = endOfDateKey(date) while (cursor < sortedFiles.length && sortedFiles[cursor].createdAt <= dayEnd) { runningBytes += sortedFiles[cursor].bytes @@ -1236,7 +1317,7 @@ async function getTopSharesByActivity( counts.set(row.targetId, item) } const topIds = [...counts.entries()] - .sort((a, b) => b[1].views + b[1].downloads - (a[1].views + a[1].downloads)) + .sort((a, b) => b[1].views - a[1].views || b[1].downloads - a[1].downloads) .slice(0, 8) .map(([id]) => id) if (topIds.length === 0) return [] @@ -1482,10 +1563,18 @@ function endOfDateKey(date: string): Date { return new Date(`${date}T23:59:59.999Z`) } +function dateKeyStart(date: string): Date { + return new Date(`${date}T00:00:00.000Z`) +} + function dayKey(date: Date): string { return date.toISOString().slice(0, 10) } +function storageUsedRollupId(date: string): string { + return `daily:${STORAGE_USED_ROLLUP_METRIC}:${date}` +} + function unixSeconds(date: Date): number { return Math.floor(date.getTime() / 1000) } diff --git a/server/http/admin-stats.integration.test.ts b/server/http/admin-stats.integration.test.ts index 1cd0f78e..3a6b8226 100644 --- a/server/http/admin-stats.integration.test.ts +++ b/server/http/admin-stats.integration.test.ts @@ -99,6 +99,42 @@ describe('admin stats routes', () => { expect(res.status).toBe(400) }) + it('does not publish admin stats routes in the OpenAPI document', async () => { + const { app } = await createTestApp() + + const res = await app.request('/api/openapi.json') + const body = (await res.json()) as { paths: Record } + + expect(res.status).toBe(200) + expect(Object.keys(body.paths).some((path) => path.startsWith('/api/admin/stats'))).toBe(false) + }) + + it('reads storage waterline trends from daily rollups when present', async () => { + const { app, db } = await createTestApp() + const headers = await adminHeaders(app) + await seedProLicense(db) + await seedStatsFixture(db) + + await db.run(sql` + INSERT INTO stats_rollups_daily ( + id, bucket_start, org_id, metric_key, dimension_key, dimension_value, + count, bytes, unique_count, metadata, updated_at + ) + VALUES ( + 'storage-used-2026-01-01', ${Date.UTC(2026, 0, 1)}, '', 'storage.used.bytes', '', '', + 0, 4096, 0, NULL, ${Date.UTC(2026, 0, 2)} + ) + `) + + const res = await app.request('/api/admin/stats/storage?from=2026-01-01&to=2026-01-01', { headers }) + const body = (await res.json()) as { + storageTrend: Array<{ date: string; usedBytes: number; newBytes: number; newFiles: number }> + } + + expect(res.status).toBe(200) + expect(body.storageTrend).toEqual([{ date: '2026-01-01', usedBytes: 4096, newBytes: 0, newFiles: 0 }]) + }) + it('returns traffic dashboard stats from audit-backed download events for Pro admins', async () => { const { app, db } = await createTestApp() const headers = await adminHeaders(app) @@ -191,6 +227,34 @@ describe('admin stats routes', () => { expect(oldRanking.storageByType).toEqual([]) expect(oldRanking.topShares).toEqual([]) }) + + it('orders top share rankings by views before downloads', async () => { + const { app, db } = await createTestApp() + const headers = await adminHeaders(app) + await seedProLicense(db) + const { orgId, userId } = await seedStatsFixture(db) + const nowSec = Math.floor(Date.now() / 1000) + const futureSec = nowSec + 7 * 24 * 60 * 60 + + await db.run(sql` + INSERT INTO shares (id, token, kind, matter_id, org_id, creator_id, expires_at, download_limit, views, downloads, status, created_at) + VALUES ('share-download-heavy', 'share-download-heavy', 'landing', 'stats-file', ${orgId}, ${userId}, ${futureSec}, 10, 0, 3, 'active', ${nowSec}) + `) + await db.run(sql` + INSERT INTO activity_events (id, org_id, user_id, actor_type, action, target_type, target_id, target_name, metadata, created_at) + VALUES + ('activity-download-heavy-1', ${orgId}, NULL, 'anonymous', 'share_download', 'share', 'share-download-heavy', 'report.pdf', '{"bytes":512,"source":"landing_share","anonymous":true}', ${nowSec}), + ('activity-download-heavy-2', ${orgId}, NULL, 'anonymous', 'share_download', 'share', 'share-download-heavy', 'report.pdf', '{"bytes":512,"source":"landing_share","anonymous":true}', ${nowSec}), + ('activity-download-heavy-3', ${orgId}, NULL, 'anonymous', 'share_download', 'share', 'share-download-heavy', 'report.pdf', '{"bytes":512,"source":"landing_share","anonymous":true}', ${nowSec}) + `) + + const res = await app.request('/api/admin/stats/ranking', { headers }) + const body = (await res.json()) as { topShares: Array<{ token: string; views: number; downloads: number }> } + + expect(res.status).toBe(200) + expect(body.topShares[0]).toMatchObject({ token: 'share-token-1', views: 1, downloads: 1 }) + expect(body.topShares[1]).toMatchObject({ token: 'share-download-heavy', views: 0, downloads: 3 }) + }) }) async function seedStatsFixture(db: Awaited>['db']) { diff --git a/server/http/admin-stats.ts b/server/http/admin-stats.ts index b6e31181..5ca250b0 100644 --- a/server/http/admin-stats.ts +++ b/server/http/admin-stats.ts @@ -1,4 +1,6 @@ -import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi' +import { zValidator } from '@hono/zod-validator' +import { Hono } from 'hono' +import { z } from 'zod' import { requireAdmin } from '../middleware/auth' import type { Env } from '../middleware/platform' import { requireFeature } from '../middleware/require-feature' @@ -12,137 +14,6 @@ import { getAdminDashboardTrafficStats, getAdminDetailedStats, } from '../usecases/admin-stats' -import { errorResponse, jsonContent } from './openapi' - -const coreStatsSchema = z - .object({ - generatedAt: z.string(), - users: z.object({ - total: z.number().int(), - admins: z.number().int(), - activeLast30Days: z.number().int(), - newLast7Days: z.number().int(), - }), - spaces: z.object({ - total: z.number().int(), - personal: z.number().int(), - team: z.number().int(), - newLast30Days: z.number().int(), - }), - storage: z.object({ - usedBytes: z.number().int(), - quotaBytes: z.number().int(), - quotaUtilization: z.number(), - capacityBytes: z.number().int(), - backendCount: z.number().int(), - activeBackendCount: z.number().int(), - }), - traffic: z.object({ - usedBytes: z.number().int(), - quotaBytes: z.number().int(), - utilization: z.number(), - period: z.string(), - }), - sharing: z.object({ - totalShares: z.number().int(), - activeShares: z.number().int(), - views: z.number().int(), - downloads: z.number().int(), - }), - operations: z.object({ - pendingInvitations: z.number().int(), - failedBackgroundJobs: z.number().int(), - offlineDownloaders: z.number().int(), - runningDownloadTasks: z.number().int(), - }), - }) - .openapi('AdminCoreStats') - -const statusCountSchema = z.object({ status: z.string(), count: z.number().int() }) - -const detailedStatsSchema = z - .object({ - generatedAt: z.string(), - periodDays: z.number().int(), - trends: z.array( - z.object({ - date: z.string(), - signups: z.number().int(), - activeUsers: z.number().int(), - shareViews: z.number().int(), - shareDownloads: z.number().int(), - remoteTasks: z.number().int(), - failedJobs: z.number().int(), - }), - ), - usageBySpace: z.array( - z.object({ - orgId: z.string(), - orgName: z.string(), - orgType: z.string(), - usedBytes: z.number().int(), - quotaBytes: z.number().int(), - utilization: z.number(), - }), - ), - storageByType: z.array(z.object({ type: z.string(), bytes: z.number().int(), files: z.number().int() })), - topShares: z.array( - z.object({ - id: z.string(), - token: z.string(), - name: z.string(), - creatorId: z.string(), - creatorName: z.string(), - views: z.number().int(), - downloads: z.number().int(), - status: z.string(), - }), - ), - sharing: z.object({ - expiredShares: z.number().int(), - revokedShares: z.number().int(), - downloadLimitHitShares: z.number().int(), - conversionRate: z.number(), - }), - remoteDownloads: z.object({ - total: z.number().int(), - completed: z.number().int(), - failed: z.number().int(), - running: z.number().int(), - successRate: z.number(), - byStatus: z.array(statusCountSchema), - failureReasons: z.array(z.object({ reason: z.string(), count: z.number().int() })), - byDownloader: z.array( - z.object({ - downloaderId: z.string(), - name: z.string(), - status: z.string(), - tasks: z.number().int(), - failedTasks: z.number().int(), - lastHeartbeatAt: z.string().nullable(), - }), - ), - }), - reliability: z.object({ - backgroundJobs: z.object({ - total: z.number().int(), - failed: z.number().int(), - failureRate: z.number(), - byStatus: z.array(statusCountSchema), - failures: z.array( - z.object({ id: z.string(), type: z.string(), errorMessage: z.string().nullable(), createdAt: z.string() }), - ), - }), - cloudTrafficReports: z.object({ pending: z.number().int(), failed: z.number().int() }), - license: z.object({ - active: z.boolean(), - edition: z.string().nullable(), - lastRefreshAt: z.string().nullable(), - lastRefreshError: z.string().nullable(), - }), - }), - }) - .openapi('AdminDetailedStats') const detailsQuerySchema = z.object({ periodDays: z.coerce.number().int().min(7).max(90).default(30), @@ -157,180 +28,6 @@ const rangeQuerySchema = z.object({ to: dashboardDateSchema.optional(), }) -const statsRangeFields = { - generatedAt: z.string(), - from: z.string(), - to: z.string(), -} - -const deltaSchema = z.object({ - value: z.number(), - previousValue: z.number(), - changePercent: z.number(), -}) - -const topShareWithPercentSchema = z.object({ - id: z.string(), - token: z.string(), - name: z.string(), - creatorId: z.string(), - creatorName: z.string(), - views: z.number(), - downloads: z.number(), - status: z.string(), - viewPercent: z.number(), - downloadPercent: z.number(), -}) - -const usageBySpaceSchema = z.object({ - orgId: z.string(), - orgName: z.string(), - orgType: z.string(), - usedBytes: z.number(), - quotaBytes: z.number(), - utilization: z.number(), -}) - -const storageByTypeSchema = z.object({ - type: z.string(), - bytes: z.number(), - files: z.number(), -}) - -const namedPercentValueSchema = z.object({ - name: z.string(), - value: z.number(), - percent: z.number(), -}) - -const namedBytesBreakdownSchema = z.object({ - name: z.string(), - bytes: z.number(), - files: z.number(), - percent: z.number(), -}) - -const dashboardOverviewStatsSchema = z - .object({ - ...statsRangeFields, - totals: z.object({ - users: z.number(), - newUsers: deltaSchema, - activeUsers: deltaSchema, - storageUsedBytes: z.number(), - storageQuotaBytes: z.number(), - trafficBytes: deltaSchema, - uploadBytes: deltaSchema, - downloadBytes: deltaSchema, - activeShares: z.number(), - shareViews: deltaSchema, - shareDownloads: deltaSchema, - }), - trends: z.array( - z.object({ - date: z.string(), - newUsers: z.number(), - activeUsers: z.number(), - storageUsedBytes: z.number(), - uploadBytes: z.number(), - downloadBytes: z.number(), - }), - ), - }) - .openapi('AdminDashboardOverviewStats') - -const dashboardGrowthStatsSchema = z - .object({ - ...statsRangeFields, - summary: z.object({ - totalUsers: z.number(), - newUsers: deltaSchema, - activeUsers: deltaSchema, - verifiedUsers: z.number(), - bannedUsers: z.number(), - silentUsers: z.number(), - }), - userScaleTrend: z.array(z.object({ date: z.string(), newUsers: z.number(), totalUsers: z.number() })), - activeUserTrend: z.array(z.object({ date: z.string(), dau: z.number(), wau: z.number(), mau: z.number() })), - userStatus: z.array(namedPercentValueSchema), - registrationSources: z.array(namedPercentValueSchema), - }) - .openapi('AdminDashboardGrowthStats') - -const dashboardStorageStatsSchema = z - .object({ - ...statsRangeFields, - summary: z.object({ - storageUsedBytes: z.number(), - quotaBytes: z.number(), - fileCount: z.number(), - newFiles: deltaSchema, - newBytes: deltaSchema, - coldFileBytes: z.number(), - }), - storageTrend: z.array( - z.object({ date: z.string(), usedBytes: z.number(), newBytes: z.number(), newFiles: z.number() }), - ), - typeBreakdown: z.array(storageByTypeSchema.extend({ percent: z.number() })), - sizeBreakdown: z.array(namedBytesBreakdownSchema), - ageBreakdown: z.array(namedBytesBreakdownSchema), - }) - .openapi('AdminDashboardStorageStats') - -const dashboardTrafficStatsSchema = z - .object({ - ...statsRangeFields, - summary: z.object({ - totalBytes: deltaSchema, - requestCount: deltaSchema, - issuedDownloads: z.number(), - blockedDownloads: z.number(), - issueRate: z.number(), - peakDailyBytes: z.number(), - }), - trafficTrend: z.array( - z.object({ date: z.string(), uploadBytes: z.number(), downloadBytes: z.number(), requests: z.number() }), - ), - sourceBreakdown: z.array( - z.object({ name: z.string(), bytes: z.number(), requests: z.number(), percent: z.number() }), - ), - issueStatus: z.array(z.object({ status: z.string(), count: z.number(), percent: z.number() })), - bandwidthTrend: z.array(z.object({ date: z.string(), bytes: z.number() })), - successTrend: z.array( - z.object({ date: z.string(), uploadSuccessRate: z.number(), downloadSuccessRate: z.number() }), - ), - failureReasons: z.array(namedPercentValueSchema), - }) - .openapi('AdminDashboardTrafficStats') - -const dashboardSharingStatsSchema = z - .object({ - ...statsRangeFields, - summary: z.object({ - activeShares: z.number(), - createdShares: deltaSchema, - views: deltaSchema, - downloads: deltaSchema, - saves: deltaSchema, - downloadConversionRate: z.number(), - }), - funnel: z.array(namedPercentValueSchema), - trend: z.array(z.object({ date: z.string(), views: z.number(), downloads: z.number(), saves: z.number() })), - typeBreakdown: z.array(namedPercentValueSchema), - sourceBreakdown: z.array(namedPercentValueSchema), - topShares: z.array(topShareWithPercentSchema), - }) - .openapi('AdminDashboardSharingStats') - -const dashboardRankingStatsSchema = z - .object({ - ...statsRangeFields, - topShares: z.array(topShareWithPercentSchema), - topSpaces: z.array(usageBySpaceSchema), - storageByType: z.array(storageByTypeSchema), - }) - .openapi('AdminDashboardRankingStats') - function parseRange(query: z.infer): { from?: Date; to?: Date } { return { from: query.from ? parseDashboardDate(query.from, 'start') : undefined, @@ -353,144 +50,27 @@ function parseDashboardDate(value: string, boundary: 'start' | 'end'): Date { return new Date(value) } -const coreRoute = createRoute({ - operationId: 'getAdminCoreStats', - summary: 'Get admin dashboard core stats', - tags: ['Admin Stats'], - method: 'get', - path: '/core', - middleware: [requireAdmin] as const, - responses: { - 200: jsonContent(coreStatsSchema, 'Admin core stats'), - 401: errorResponse('Unauthorized'), - }, -}) - -const detailsRoute = createRoute({ - operationId: 'getAdminDetailedStats', - summary: 'Get admin dashboard detailed stats', - tags: ['Admin Stats'], - method: 'get', - path: '/details', - middleware: [requireAdmin, requireFeature('analytics')] as const, - request: { query: detailsQuerySchema }, - responses: { - 200: jsonContent(detailedStatsSchema, 'Admin detailed stats'), - 402: errorResponse('Feature not available'), - }, -}) - -const overviewRoute = createRoute({ - operationId: 'getAdminDashboardOverviewStats', - summary: 'Get admin dashboard overview stats', - tags: ['Admin Stats'], - method: 'get', - path: '/overview', - middleware: [requireAdmin] as const, - request: { query: rangeQuerySchema }, - responses: { - 200: jsonContent(dashboardOverviewStatsSchema, 'Admin dashboard overview stats'), - 400: errorResponse('Invalid query'), - 401: errorResponse('Unauthorized'), - }, -}) - -const growthRoute = createRoute({ - operationId: 'getAdminDashboardGrowthStats', - summary: 'Get admin dashboard growth stats', - tags: ['Admin Stats'], - method: 'get', - path: '/growth', - middleware: [requireAdmin, requireFeature('analytics')] as const, - request: { query: rangeQuerySchema }, - responses: { - 200: jsonContent(dashboardGrowthStatsSchema, 'Admin dashboard growth stats'), - 400: errorResponse('Invalid query'), - 402: errorResponse('Feature not available'), - }, -}) - -const storageRoute = createRoute({ - operationId: 'getAdminDashboardStorageStats', - summary: 'Get admin dashboard storage stats', - tags: ['Admin Stats'], - method: 'get', - path: '/storage', - middleware: [requireAdmin, requireFeature('analytics')] as const, - request: { query: rangeQuerySchema }, - responses: { - 200: jsonContent(dashboardStorageStatsSchema, 'Admin dashboard storage stats'), - 400: errorResponse('Invalid query'), - 402: errorResponse('Feature not available'), - }, -}) - -const trafficRoute = createRoute({ - operationId: 'getAdminDashboardTrafficStats', - summary: 'Get admin dashboard traffic stats', - tags: ['Admin Stats'], - method: 'get', - path: '/traffic', - middleware: [requireAdmin, requireFeature('analytics')] as const, - request: { query: rangeQuerySchema }, - responses: { - 200: jsonContent(dashboardTrafficStatsSchema, 'Admin dashboard traffic stats'), - 400: errorResponse('Invalid query'), - 402: errorResponse('Feature not available'), - }, -}) - -const sharingRoute = createRoute({ - operationId: 'getAdminDashboardSharingStats', - summary: 'Get admin dashboard sharing stats', - tags: ['Admin Stats'], - method: 'get', - path: '/sharing', - middleware: [requireAdmin, requireFeature('analytics')] as const, - request: { query: rangeQuerySchema }, - responses: { - 200: jsonContent(dashboardSharingStatsSchema, 'Admin dashboard sharing stats'), - 400: errorResponse('Invalid query'), - 402: errorResponse('Feature not available'), - }, -}) - -const rankingRoute = createRoute({ - operationId: 'getAdminDashboardRankingStats', - summary: 'Get admin dashboard ranking stats', - tags: ['Admin Stats'], - method: 'get', - path: '/ranking', - middleware: [requireAdmin, requireFeature('analytics')] as const, - request: { query: rangeQuerySchema }, - responses: { - 200: jsonContent(dashboardRankingStatsSchema, 'Admin dashboard ranking stats'), - 400: errorResponse('Invalid query'), - 402: errorResponse('Feature not available'), - }, -}) - -export const adminStats = new OpenAPIHono() - .openapi(coreRoute, async (c) => c.json(await getAdminCoreStats(c.get('deps')), 200)) - .openapi(detailsRoute, async (c) => { +export const adminStats = new Hono() + .get('/core', requireAdmin, async (c) => c.json(await getAdminCoreStats(c.get('deps')), 200)) + .get('/details', requireAdmin, requireFeature('analytics'), zValidator('query', detailsQuerySchema), async (c) => { const { periodDays } = c.req.valid('query') return c.json(await getAdminDetailedStats(c.get('deps'), { periodDays }), 200) }) - .openapi(overviewRoute, async (c) => + .get('/overview', requireAdmin, zValidator('query', rangeQuerySchema), async (c) => c.json(await getAdminDashboardOverviewStats(c.get('deps'), parseRange(c.req.valid('query'))), 200), ) - .openapi(growthRoute, async (c) => + .get('/growth', requireAdmin, requireFeature('analytics'), zValidator('query', rangeQuerySchema), async (c) => c.json(await getAdminDashboardGrowthStats(c.get('deps'), parseRange(c.req.valid('query'))), 200), ) - .openapi(storageRoute, async (c) => + .get('/storage', requireAdmin, requireFeature('analytics'), zValidator('query', rangeQuerySchema), async (c) => c.json(await getAdminDashboardStorageStats(c.get('deps'), parseRange(c.req.valid('query'))), 200), ) - .openapi(trafficRoute, async (c) => + .get('/traffic', requireAdmin, requireFeature('analytics'), zValidator('query', rangeQuerySchema), async (c) => c.json(await getAdminDashboardTrafficStats(c.get('deps'), parseRange(c.req.valid('query'))), 200), ) - .openapi(sharingRoute, async (c) => + .get('/sharing', requireAdmin, requireFeature('analytics'), zValidator('query', rangeQuerySchema), async (c) => c.json(await getAdminDashboardSharingStats(c.get('deps'), parseRange(c.req.valid('query'))), 200), ) - .openapi(rankingRoute, async (c) => + .get('/ranking', requireAdmin, requireFeature('analytics'), zValidator('query', rangeQuerySchema), async (c) => c.json(await getAdminDashboardRankingStats(c.get('deps'), parseRange(c.req.valid('query'))), 200), )