2015-02-12 08:46:14 -06:00
package api
import (
2021-06-14 10:36:48 -05:00
"context"
"net/http"
2023-11-29 10:58:41 -06:00
"time"
2021-06-14 10:36:48 -05:00
2021-01-15 07:43:20 -06:00
"github.com/grafana/grafana/pkg/api/response"
2021-08-24 04:36:28 -05:00
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
2023-08-18 05:42:18 -05:00
"github.com/grafana/grafana/pkg/services/auth/identity"
2023-01-27 01:50:36 -06:00
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
2023-01-17 07:17:54 -06:00
"github.com/grafana/grafana/pkg/services/stats"
2021-06-14 10:36:48 -05:00
"github.com/grafana/grafana/pkg/setting"
2015-02-12 08:46:14 -06:00
)
2022-07-27 08:54:37 -05:00
// swagger:route GET /admin/settings admin adminGetSettings
//
// Fetch settings.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `settings:read` and scopes: `settings:*`, `settings:auth.saml:` and `settings:auth.saml:enabled` (property level).
//
// Security:
// - basic:
//
// Responses:
// 200: adminGetSettingsResponse
// 401: unauthorisedError
// 403: forbiddenError
2023-01-27 01:50:36 -06:00
func ( hs * HTTPServer ) AdminGetSettings ( c * contextmodel . ReqContext ) response . Response {
2021-06-14 10:36:48 -05:00
settings , err := hs . getAuthorizedSettings ( c . Req . Context ( ) , c . SignedInUser , hs . SettingsProvider . Current ( ) )
if err != nil {
return response . Error ( http . StatusForbidden , "Failed to authorize settings" , err )
}
return response . JSON ( http . StatusOK , settings )
2015-02-12 08:46:14 -06:00
}
2016-01-24 13:01:33 -06:00
2023-04-20 03:43:28 -05:00
func ( hs * HTTPServer ) AdminGetVerboseSettings ( c * contextmodel . ReqContext ) response . Response {
bag := hs . SettingsProvider . CurrentVerbose ( )
if bag == nil {
return response . JSON ( http . StatusNotImplemented , make ( map [ string ] string ) )
}
verboseSettings , err := hs . getAuthorizedVerboseSettings ( c . Req . Context ( ) , c . SignedInUser , bag )
if err != nil {
return response . Error ( http . StatusForbidden , "Failed to authorize settings" , err )
}
return response . JSON ( http . StatusOK , verboseSettings )
}
2022-07-27 08:54:37 -05:00
// swagger:route GET /admin/stats admin adminGetStats
//
// Fetch Grafana Stats.
//
// Only works with Basic Authentication (username and password). See introduction for an explanation.
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `server:stats:read`.
//
// Responses:
// 200: adminGetStatsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
2023-01-27 01:50:36 -06:00
func ( hs * HTTPServer ) AdminGetStats ( c * contextmodel . ReqContext ) response . Response {
2023-03-30 01:08:47 -05:00
adminStats , err := hs . statsService . GetAdminStats ( c . Req . Context ( ) , & stats . GetAdminStatsQuery { } )
if err != nil {
2021-01-15 07:43:20 -06:00
return response . Error ( 500 , "Failed to get admin stats from database" , err )
2016-01-24 23:18:17 -06:00
}
2023-11-29 10:58:41 -06:00
thirtyDays := 30 * 24 * time . Hour
devicesCount , err := hs . anonService . CountDevices ( c . Req . Context ( ) , time . Now ( ) . Add ( - thirtyDays ) , time . Now ( ) . Add ( time . Minute ) )
if err != nil {
return response . Error ( 500 , "Failed to get anon stats from database" , err )
}
adminStats . AnonymousStats . ActiveDevices = devicesCount
2016-01-24 23:18:17 -06:00
2023-03-30 01:08:47 -05:00
return response . JSON ( http . StatusOK , adminStats )
2016-01-24 13:01:33 -06:00
}
2021-06-14 10:36:48 -05:00
2023-08-18 05:42:18 -05:00
func ( hs * HTTPServer ) getAuthorizedSettings ( ctx context . Context , user identity . Requester , bag setting . SettingsBag ) ( setting . SettingsBag , error ) {
2021-08-24 04:36:28 -05:00
eval := func ( scope string ) ( bool , error ) {
return hs . AccessControl . Evaluate ( ctx , user , ac . EvalPermission ( ac . ActionSettingsRead , scope ) )
2021-06-14 10:36:48 -05:00
}
2021-08-24 04:36:28 -05:00
ok , err := eval ( ac . ScopeSettingsAll )
2021-06-14 10:36:48 -05:00
if err != nil {
return nil , err
}
if ok {
return bag , nil
}
authorizedBag := make ( setting . SettingsBag )
for section , keys := range bag {
2021-08-24 04:36:28 -05:00
ok , err := eval ( ac . Scope ( "settings" , section , "*" ) )
2021-06-14 10:36:48 -05:00
if err != nil {
return nil , err
}
if ok {
authorizedBag [ section ] = keys
continue
}
for key := range keys {
2021-08-24 04:36:28 -05:00
ok , err := eval ( ac . Scope ( "settings" , section , key ) )
2021-06-14 10:36:48 -05:00
if err != nil {
return nil , err
}
if ok {
if _ , exists := authorizedBag [ section ] ; ! exists {
authorizedBag [ section ] = make ( map [ string ] string )
}
authorizedBag [ section ] [ key ] = bag [ section ] [ key ]
}
}
}
return authorizedBag , nil
}
2022-07-27 08:54:37 -05:00
2023-08-18 05:42:18 -05:00
func ( hs * HTTPServer ) getAuthorizedVerboseSettings ( ctx context . Context , user identity . Requester , bag setting . VerboseSettingsBag ) ( setting . VerboseSettingsBag , error ) {
2023-04-20 03:43:28 -05:00
eval := func ( scope string ) ( bool , error ) {
return hs . AccessControl . Evaluate ( ctx , user , ac . EvalPermission ( ac . ActionSettingsRead , scope ) )
}
ok , err := eval ( ac . ScopeSettingsAll )
if err != nil {
return nil , err
}
if ok {
return bag , nil
}
authorizedBag := make ( setting . VerboseSettingsBag )
for section , keys := range bag {
ok , err := eval ( ac . Scope ( "settings" , section , "*" ) )
if err != nil {
return nil , err
}
if ok {
authorizedBag [ section ] = keys
continue
}
for key := range keys {
ok , err := eval ( ac . Scope ( "settings" , section , key ) )
if err != nil {
return nil , err
}
if ! ok {
continue
}
if _ , exists := authorizedBag [ section ] ; ! exists {
authorizedBag [ section ] = make ( map [ string ] map [ setting . VerboseSourceType ] string )
}
authorizedBag [ section ] [ key ] = bag [ section ] [ key ]
}
}
return authorizedBag , nil
}
2022-07-27 08:54:37 -05:00
// swagger:response adminGetSettingsResponse
type GetSettingsResponse struct {
// in:body
Body setting . SettingsBag ` json:"body" `
}
// swagger:response adminGetStatsResponse
type GetStatsResponse struct {
// in:body
2023-01-17 07:17:54 -06:00
Body stats . AdminStats ` json:"body" `
2022-07-27 08:54:37 -05:00
}