2015-03-21 07:53:16 -05:00
package api
import (
2018-12-10 15:36:32 -06:00
"bytes"
"encoding/json"
2022-06-16 06:13:58 -05:00
"errors"
2018-12-10 15:36:32 -06:00
"fmt"
"net/http"
2015-03-25 03:04:38 -05:00
"time"
2015-03-21 09:56:26 -05:00
"github.com/grafana/grafana/pkg/api/dtos"
2021-01-15 07:43:20 -06:00
"github.com/grafana/grafana/pkg/api/response"
2018-12-10 15:36:32 -06:00
"github.com/grafana/grafana/pkg/components/simplejson"
2019-02-23 16:35:26 -06:00
"github.com/grafana/grafana/pkg/infra/metrics"
2020-03-04 05:57:20 -06:00
"github.com/grafana/grafana/pkg/models"
2022-06-30 08:31:54 -05:00
"github.com/grafana/grafana/pkg/services/dashboards"
2022-06-17 08:09:01 -05:00
"github.com/grafana/grafana/pkg/services/dashboardsnapshots"
2018-02-20 16:26:08 -06:00
"github.com/grafana/grafana/pkg/services/guardian"
2015-03-25 03:04:38 -05:00
"github.com/grafana/grafana/pkg/setting"
2015-03-21 07:53:16 -05:00
"github.com/grafana/grafana/pkg/util"
2021-10-11 07:30:59 -05:00
"github.com/grafana/grafana/pkg/web"
2015-03-21 07:53:16 -05:00
)
2018-12-10 15:36:32 -06:00
var client = & http . Client {
Timeout : time . Second * 5 ,
Transport : & http . Transport { Proxy : http . ProxyFromEnvironment } ,
}
2022-07-27 08:54:37 -05:00
// swagger:route GET /snapshot/shared-options snapshots getSharingOptions
//
// Get snapshot sharing settings.
//
// Responses:
// 200: getSharingOptionsResponse
// 401: unauthorisedError
2020-03-04 05:57:20 -06:00
func GetSharingOptions ( c * models . ReqContext ) {
2022-04-15 07:01:58 -05:00
c . JSON ( http . StatusOK , util . DynMap {
2015-10-14 09:39:57 -05:00
"externalSnapshotURL" : setting . ExternalSnapshotUrl ,
"externalSnapshotName" : setting . ExternalSnapshotName ,
"externalEnabled" : setting . ExternalEnabled ,
} )
}
2018-12-10 15:36:32 -06:00
type CreateExternalSnapshotResponse struct {
Key string ` json:"key" `
DeleteKey string ` json:"deleteKey" `
Url string ` json:"url" `
DeleteUrl string ` json:"deleteUrl" `
}
2022-06-17 08:09:01 -05:00
func createExternalDashboardSnapshot ( cmd dashboardsnapshots . CreateDashboardSnapshotCommand ) ( * CreateExternalSnapshotResponse , error ) {
2018-12-10 15:36:32 -06:00
var createSnapshotResponse CreateExternalSnapshotResponse
message := map [ string ] interface { } {
"name" : cmd . Name ,
"expires" : cmd . Expires ,
"dashboard" : cmd . Dashboard ,
2021-05-13 17:39:43 -05:00
"key" : cmd . Key ,
"deleteKey" : cmd . DeleteKey ,
2018-12-10 15:36:32 -06:00
}
messageBytes , err := simplejson . NewFromAny ( message ) . Encode ( )
if err != nil {
return nil , err
}
response , err := client . Post ( setting . ExternalSnapshotUrl + "/api/snapshots" , "application/json" , bytes . NewBuffer ( messageBytes ) )
if err != nil {
return nil , err
}
2020-12-15 02:32:06 -06:00
defer func ( ) {
if err := response . Body . Close ( ) ; err != nil {
plog . Warn ( "Failed to close response body" , "err" , err )
}
} ( )
2018-12-10 15:36:32 -06:00
if response . StatusCode != 200 {
2020-11-05 06:07:06 -06:00
return nil , fmt . Errorf ( "create external snapshot response status code %d" , response . StatusCode )
2018-12-10 15:36:32 -06:00
}
if err := json . NewDecoder ( response . Body ) . Decode ( & createSnapshotResponse ) ; err != nil {
return nil , err
}
return & createSnapshotResponse , nil
}
2022-12-13 07:48:54 -06:00
func createOriginalDashboardURL ( appURL string , cmd * dashboardsnapshots . CreateDashboardSnapshotCommand ) ( string , error ) {
dashUID := cmd . Dashboard . Get ( "uid" ) . MustString ( "" )
if ok := util . IsValidShortUID ( dashUID ) ; ! ok {
return "" , fmt . Errorf ( "invalid dashboard UID" )
}
return fmt . Sprintf ( "/d/%v" , dashUID ) , nil
}
2022-07-27 08:54:37 -05:00
// swagger:route POST /snapshots snapshots createDashboardSnapshot
//
// When creating a snapshot using the API, you have to provide the full dashboard payload including the snapshot data. This endpoint is designed for the Grafana UI.
//
// Snapshot public mode should be enabled or authentication is required.
//
// Responses:
// 200: createDashboardSnapshotResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
2022-02-08 10:57:59 -06:00
func ( hs * HTTPServer ) CreateDashboardSnapshot ( c * models . ReqContext ) response . Response {
2022-06-17 08:09:01 -05:00
cmd := dashboardsnapshots . CreateDashboardSnapshotCommand { }
2021-11-29 12:05:20 -06:00
if err := web . Bind ( c . Req , & cmd ) ; err != nil {
return response . Error ( http . StatusBadRequest , "bad request data" , err )
}
2016-04-21 02:59:48 -05:00
if cmd . Name == "" {
cmd . Name = "Unnamed snapshot"
}
2022-12-13 07:48:54 -06:00
var snapshotUrl string
2023-01-25 08:09:44 -06:00
cmd . ExternalURL = ""
cmd . OrgID = c . OrgID
cmd . UserID = c . UserID
2022-12-13 07:48:54 -06:00
originalDashboardURL , err := createOriginalDashboardURL ( hs . Cfg . AppURL , & cmd )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Invalid app URL" , err )
}
2018-12-10 15:36:32 -06:00
2015-03-25 03:04:38 -05:00
if cmd . External {
2018-12-10 15:36:32 -06:00
if ! setting . ExternalEnabled {
2022-08-30 10:19:52 -05:00
c . JsonApiErr ( http . StatusForbidden , "External dashboard creation is disabled" , nil )
2021-11-29 12:05:20 -06:00
return nil
2018-12-10 15:36:32 -06:00
}
response , err := createExternalDashboardSnapshot ( cmd )
if err != nil {
2022-08-30 10:19:52 -05:00
c . JsonApiErr ( http . StatusInternalServerError , "Failed to create external snapshot" , err )
2021-11-29 12:05:20 -06:00
return nil
2015-03-26 14:59:41 -05:00
}
2022-12-13 07:48:54 -06:00
snapshotUrl = response . Url
2018-12-10 15:36:32 -06:00
cmd . Key = response . Key
cmd . DeleteKey = response . DeleteKey
2023-01-25 08:09:44 -06:00
cmd . ExternalURL = response . Url
cmd . ExternalDeleteURL = response . DeleteUrl
2018-12-10 15:36:32 -06:00
cmd . Dashboard = simplejson . New ( )
2019-07-16 09:58:46 -05:00
metrics . MApiDashboardSnapshotExternal . Inc ( )
2015-03-26 06:00:52 -05:00
} else {
2022-12-13 07:48:54 -06:00
cmd . Dashboard . SetPath ( [ ] string { "snapshot" , "originalUrl" } , originalDashboardURL )
2019-05-09 04:53:04 -05:00
if cmd . Key == "" {
2019-10-23 03:40:12 -05:00
var err error
cmd . Key , err = util . GetRandomString ( 32 )
if err != nil {
2022-08-30 10:19:52 -05:00
c . JsonApiErr ( http . StatusInternalServerError , "Could not generate random string" , err )
2021-11-29 12:05:20 -06:00
return nil
2019-10-23 03:40:12 -05:00
}
2019-05-09 04:53:04 -05:00
}
if cmd . DeleteKey == "" {
2019-10-23 03:40:12 -05:00
var err error
cmd . DeleteKey , err = util . GetRandomString ( 32 )
if err != nil {
2022-08-30 10:19:52 -05:00
c . JsonApiErr ( http . StatusInternalServerError , "Could not generate random string" , err )
2021-11-29 12:05:20 -06:00
return nil
2019-10-23 03:40:12 -05:00
}
2019-05-09 04:53:04 -05:00
}
2022-12-13 07:48:54 -06:00
snapshotUrl = setting . ToAbsUrl ( "dashboard/snapshot/" + cmd . Key )
2018-12-10 15:36:32 -06:00
2019-07-16 09:58:46 -05:00
metrics . MApiDashboardSnapshotCreate . Inc ( )
2015-03-25 03:04:38 -05:00
}
2015-03-21 07:53:16 -05:00
2023-01-25 08:09:44 -06:00
result , err := hs . dashboardsnapshotsService . CreateDashboardSnapshot ( c . Req . Context ( ) , & cmd )
if err != nil {
2022-08-30 10:19:52 -05:00
c . JsonApiErr ( http . StatusInternalServerError , "Failed to create snapshot" , err )
2021-11-29 12:05:20 -06:00
return nil
2015-03-21 07:53:16 -05:00
}
2022-04-15 07:01:58 -05:00
c . JSON ( http . StatusOK , util . DynMap {
2015-03-26 14:34:58 -05:00
"key" : cmd . Key ,
"deleteKey" : cmd . DeleteKey ,
2022-12-13 07:48:54 -06:00
"url" : snapshotUrl ,
2015-03-26 14:34:58 -05:00
"deleteUrl" : setting . ToAbsUrl ( "api/snapshots-delete/" + cmd . DeleteKey ) ,
2023-01-25 08:09:44 -06:00
"id" : result . ID ,
2015-03-26 14:34:58 -05:00
} )
2021-11-29 12:05:20 -06:00
return nil
2015-03-25 03:04:38 -05:00
}
2018-02-20 16:26:08 -06:00
// GET /api/snapshots/:key
2022-07-27 08:54:37 -05:00
// swagger:route GET /snapshots/{key} snapshots getDashboardSnapshot
//
// Get Snapshot by Key.
//
// Responses:
// 200: getDashboardSnapshotResponse
2022-08-03 09:31:23 -05:00
// 400: badRequestError
2022-07-27 08:54:37 -05:00
// 404: notFoundError
// 500: internalServerError
2022-02-08 10:57:59 -06:00
func ( hs * HTTPServer ) GetDashboardSnapshot ( c * models . ReqContext ) response . Response {
2021-10-11 07:30:59 -05:00
key := web . Params ( c . Req ) [ ":key" ]
2021-10-05 12:38:09 -05:00
if len ( key ) == 0 {
2022-08-03 09:31:23 -05:00
return response . Error ( http . StatusBadRequest , "Empty snapshot key" , nil )
2021-10-05 12:38:09 -05:00
}
2022-06-17 08:09:01 -05:00
query := & dashboardsnapshots . GetDashboardSnapshotQuery { Key : key }
2015-03-21 07:53:16 -05:00
2023-01-25 08:09:44 -06:00
queryResult , err := hs . dashboardsnapshotsService . GetDashboardSnapshot ( c . Req . Context ( ) , query )
2015-03-21 07:53:16 -05:00
if err != nil {
2022-08-03 09:31:23 -05:00
return response . Err ( err )
2015-03-21 07:53:16 -05:00
}
2023-01-25 08:09:44 -06:00
snapshot := queryResult
2015-03-26 06:00:52 -05:00
// expired snapshots should also be removed from db
if snapshot . Expires . Before ( time . Now ( ) ) {
2021-01-15 07:43:20 -06:00
return response . Error ( 404 , "Dashboard snapshot not found" , err )
2020-10-13 03:19:42 -05:00
}
2015-05-04 01:36:44 -05:00
dto := dtos . DashboardFullWithMeta {
2021-09-01 06:05:15 -05:00
Dashboard : snapshot . Dashboard ,
2015-03-28 11:53:52 -05:00
Meta : dtos . DashboardMeta {
2023-01-18 06:52:41 -06:00
Type : dashboards . DashTypeSnapshot ,
2015-03-28 11:53:52 -05:00
IsSnapshot : true ,
Created : snapshot . Created ,
Expires : snapshot . Expires ,
} ,
2015-03-21 09:56:26 -05:00
}
2019-07-16 09:58:46 -05:00
metrics . MApiDashboardSnapshotGet . Inc ( )
2015-03-24 10:49:12 -05:00
2022-04-15 07:01:58 -05:00
return response . JSON ( http . StatusOK , dto ) . SetHeader ( "Cache-Control" , "public, max-age=3600" )
2015-03-26 14:34:58 -05:00
}
2015-03-26 06:00:52 -05:00
2018-12-10 15:40:26 -06:00
func deleteExternalDashboardSnapshot ( externalUrl string ) error {
response , err := client . Get ( externalUrl )
if err != nil {
return err
}
2021-07-15 08:29:52 -05:00
defer func ( ) {
if err := response . Body . Close ( ) ; err != nil {
plog . Warn ( "Failed to close response body" , "err" , err )
}
} ( )
2018-12-10 15:40:26 -06:00
if response . StatusCode == 200 {
return nil
}
// Gracefully ignore "snapshot not found" errors as they could have already
// been removed either via the cleanup script or by request.
if response . StatusCode == 500 {
var respJson map [ string ] interface { }
if err := json . NewDecoder ( response . Body ) . Decode ( & respJson ) ; err != nil {
return err
}
if respJson [ "message" ] == "Failed to get dashboard snapshot" {
return nil
}
}
2020-11-05 06:07:06 -06:00
return fmt . Errorf ( "unexpected response when deleting external snapshot, status code: %d" , response . StatusCode )
2018-12-10 15:40:26 -06:00
}
2022-07-27 08:54:37 -05:00
// swagger:route GET /snapshots-delete/{deleteKey} snapshots deleteDashboardSnapshotByDeleteKey
//
// Delete Snapshot by deleteKey.
//
// Snapshot public mode should be enabled or authentication is required.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
2022-02-08 10:57:59 -06:00
func ( hs * HTTPServer ) DeleteDashboardSnapshotByDeleteKey ( c * models . ReqContext ) response . Response {
2021-10-11 07:30:59 -05:00
key := web . Params ( c . Req ) [ ":deleteKey" ]
2021-10-05 12:38:09 -05:00
if len ( key ) == 0 {
return response . Error ( 404 , "Snapshot not found" , nil )
}
2018-05-24 01:55:16 -05:00
2022-06-17 08:09:01 -05:00
query := & dashboardsnapshots . GetDashboardSnapshotQuery { DeleteKey : key }
2023-01-25 08:09:44 -06:00
queryResult , err := hs . dashboardsnapshotsService . GetDashboardSnapshot ( c . Req . Context ( ) , query )
2018-05-24 01:55:16 -05:00
if err != nil {
2022-08-03 09:31:23 -05:00
return response . Err ( err )
2018-05-24 01:55:16 -05:00
}
2023-01-25 08:09:44 -06:00
if queryResult . External {
err := deleteExternalDashboardSnapshot ( queryResult . ExternalDeleteURL )
2018-12-10 15:40:26 -06:00
if err != nil {
2021-01-15 07:43:20 -06:00
return response . Error ( 500 , "Failed to delete external dashboard" , err )
2018-12-10 15:40:26 -06:00
}
}
2023-01-25 08:09:44 -06:00
cmd := & dashboardsnapshots . DeleteDashboardSnapshotCommand { DeleteKey : queryResult . DeleteKey }
2018-05-24 01:55:16 -05:00
2022-06-14 12:41:29 -05:00
if err := hs . dashboardsnapshotsService . DeleteDashboardSnapshot ( c . Req . Context ( ) , cmd ) ; err != nil {
2021-01-15 07:43:20 -06:00
return response . Error ( 500 , "Failed to delete dashboard snapshot" , err )
2018-05-24 01:55:16 -05:00
}
2022-04-15 07:01:58 -05:00
return response . JSON ( http . StatusOK , util . DynMap {
2020-12-04 09:22:58 -06:00
"message" : "Snapshot deleted. It might take an hour before it's cleared from any CDN caches." ,
2023-01-25 08:09:44 -06:00
"id" : queryResult . ID ,
2020-12-04 09:22:58 -06:00
} )
2018-05-24 01:55:16 -05:00
}
2022-07-27 08:54:37 -05:00
// swagger:route DELETE /snapshots/{key} snapshots deleteDashboardSnapshot
//
// Delete Snapshot by Key.
//
// Responses:
// 200: okResponse
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
2022-02-08 10:57:59 -06:00
func ( hs * HTTPServer ) DeleteDashboardSnapshot ( c * models . ReqContext ) response . Response {
2021-10-11 07:30:59 -05:00
key := web . Params ( c . Req ) [ ":key" ]
2021-10-05 12:38:09 -05:00
if len ( key ) == 0 {
2022-08-30 10:19:52 -05:00
return response . Error ( http . StatusNotFound , "Snapshot not found" , nil )
2021-10-05 12:38:09 -05:00
}
2018-02-20 16:26:08 -06:00
2022-06-17 08:09:01 -05:00
query := & dashboardsnapshots . GetDashboardSnapshotQuery { Key : key }
2018-02-20 16:26:08 -06:00
2023-01-25 08:09:44 -06:00
queryResult , err := hs . dashboardsnapshotsService . GetDashboardSnapshot ( c . Req . Context ( ) , query )
2018-02-20 16:26:08 -06:00
if err != nil {
2022-08-03 09:31:23 -05:00
return response . Err ( err )
2018-02-20 16:26:08 -06:00
}
2023-01-25 08:09:44 -06:00
if queryResult == nil {
2022-08-30 10:19:52 -05:00
return response . Error ( http . StatusNotFound , "Failed to get dashboard snapshot" , nil )
2018-02-20 16:26:08 -06:00
}
2020-11-13 02:52:38 -06:00
2023-01-25 08:09:44 -06:00
if queryResult . External {
err := deleteExternalDashboardSnapshot ( queryResult . ExternalDeleteURL )
2018-12-10 15:40:26 -06:00
if err != nil {
2022-08-30 10:19:52 -05:00
return response . Error ( http . StatusInternalServerError , "Failed to delete external dashboard" , err )
2018-12-10 15:40:26 -06:00
}
2022-08-30 10:19:52 -05:00
}
2022-07-07 08:15:39 -05:00
2022-08-30 10:19:52 -05:00
// Dashboard can be empty (creation error or external snapshot). This means that the mustInt here returns a 0,
// which before RBAC would result in a dashboard which has no ACL. A dashboard without an ACL would fallback
// to the user’ s org role, which for editors and admins would essentially always be allowed here. With RBAC,
// all permissions must be explicit, so the lack of a rule for dashboard 0 means the guardian will reject.
2023-01-25 08:09:44 -06:00
dashboardID := queryResult . Dashboard . Get ( "id" ) . MustInt64 ( )
2022-08-30 10:19:52 -05:00
if dashboardID != 0 {
2022-12-15 08:34:17 -06:00
guardian , err := guardian . New ( c . Req . Context ( ) , dashboardID , c . OrgID , c . SignedInUser )
if err != nil {
return response . Err ( err )
}
2022-07-07 08:15:39 -05:00
canEdit , err := guardian . CanEdit ( )
2022-08-30 10:19:52 -05:00
// check for permissions only if the dashboard is found
2022-07-07 08:15:39 -05:00
if err != nil && ! errors . Is ( err , dashboards . ErrDashboardNotFound ) {
2022-08-30 10:19:52 -05:00
return response . Error ( http . StatusInternalServerError , "Error while checking permissions for snapshot" , err )
2022-07-07 08:15:39 -05:00
}
2023-01-25 08:09:44 -06:00
if ! canEdit && queryResult . UserID != c . SignedInUser . UserID && ! errors . Is ( err , dashboards . ErrDashboardNotFound ) {
2022-08-30 10:19:52 -05:00
return response . Error ( http . StatusForbidden , "Access denied to this snapshot" , nil )
2022-07-07 08:15:39 -05:00
}
2018-12-10 15:40:26 -06:00
}
2023-01-25 08:09:44 -06:00
cmd := & dashboardsnapshots . DeleteDashboardSnapshotCommand { DeleteKey : queryResult . DeleteKey }
2015-03-24 10:49:12 -05:00
2022-06-14 12:41:29 -05:00
if err := hs . dashboardsnapshotsService . DeleteDashboardSnapshot ( c . Req . Context ( ) , cmd ) ; err != nil {
2022-08-30 10:19:52 -05:00
return response . Error ( http . StatusInternalServerError , "Failed to delete dashboard snapshot" , err )
2015-03-26 14:34:58 -05:00
}
2022-04-15 07:01:58 -05:00
return response . JSON ( http . StatusOK , util . DynMap {
2020-12-04 09:22:58 -06:00
"message" : "Snapshot deleted. It might take an hour before it's cleared from any CDN caches." ,
2023-01-25 08:09:44 -06:00
"id" : queryResult . ID ,
2020-12-04 09:22:58 -06:00
} )
2015-03-21 07:53:16 -05:00
}
2016-01-19 03:37:36 -06:00
2022-07-27 08:54:37 -05:00
// swagger:route GET /dashboard/snapshots snapshots searchDashboardSnapshots
//
// List snapshots.
//
// Responses:
// 200: searchDashboardSnapshotsResponse
// 500: internalServerError
2022-02-08 10:57:59 -06:00
func ( hs * HTTPServer ) SearchDashboardSnapshots ( c * models . ReqContext ) response . Response {
2016-01-19 07:05:24 -06:00
query := c . Query ( "query" )
limit := c . QueryInt ( "limit" )
2016-01-19 03:37:36 -06:00
2016-01-19 07:05:24 -06:00
if limit == 0 {
limit = 1000
}
2016-01-19 03:37:36 -06:00
2022-06-17 08:09:01 -05:00
searchQuery := dashboardsnapshots . GetDashboardSnapshotsQuery {
2018-02-20 16:26:08 -06:00
Name : query ,
Limit : limit ,
2023-01-25 08:09:44 -06:00
OrgID : c . OrgID ,
2018-02-20 16:26:08 -06:00
SignedInUser : c . SignedInUser ,
2016-01-19 07:05:24 -06:00
}
2016-01-19 03:37:36 -06:00
2023-01-25 08:09:44 -06:00
searchQueryResult , err := hs . dashboardsnapshotsService . SearchDashboardSnapshots ( c . Req . Context ( ) , & searchQuery )
2016-01-19 07:05:24 -06:00
if err != nil {
2021-01-15 07:43:20 -06:00
return response . Error ( 500 , "Search failed" , err )
2016-01-19 07:05:24 -06:00
}
2016-01-19 03:37:36 -06:00
2023-01-25 08:09:44 -06:00
dtos := make ( [ ] * dashboardsnapshots . DashboardSnapshotDTO , len ( searchQueryResult ) )
for i , snapshot := range searchQueryResult {
2022-06-17 08:09:01 -05:00
dtos [ i ] = & dashboardsnapshots . DashboardSnapshotDTO {
2023-01-25 08:09:44 -06:00
ID : snapshot . ID ,
2016-01-20 01:23:44 -06:00
Name : snapshot . Name ,
Key : snapshot . Key ,
2023-01-25 08:09:44 -06:00
OrgID : snapshot . OrgID ,
UserID : snapshot . UserID ,
2016-01-20 01:23:44 -06:00
External : snapshot . External ,
2023-01-25 08:09:44 -06:00
ExternalURL : snapshot . ExternalURL ,
2016-01-20 01:23:44 -06:00
Expires : snapshot . Expires ,
Created : snapshot . Created ,
Updated : snapshot . Updated ,
}
}
2022-04-15 07:01:58 -05:00
return response . JSON ( http . StatusOK , dtos )
2016-01-19 03:37:36 -06:00
}
2022-07-27 08:54:37 -05:00
// swagger:parameters createDashboardSnapshot
type CreateSnapshotParams struct {
// in:body
// required:true
Body dashboardsnapshots . CreateDashboardSnapshotCommand ` json:"body" `
}
// swagger:parameters searchDashboardSnapshots
type GetSnapshotsParams struct {
// Search Query
// in:query
Query string ` json:"query" `
// Limit the number of returned results
// in:query
// default:1000
Limit int64 ` json:"limit" `
}
// swagger:parameters getDashboardSnapshot
type GetDashboardSnapshotParams struct {
// in:path
Key string ` json:"key" `
}
// swagger:parameters deleteDashboardSnapshot
type DeleteDashboardSnapshotParams struct {
// in:path
Key string ` json:"key" `
}
// swagger:parameters deleteDashboardSnapshotByDeleteKey
type DeleteSnapshotByDeleteKeyParams struct {
// in:path
DeleteKey string ` json:"deleteKey" `
}
// swagger:response createDashboardSnapshotResponse
type CreateSnapshotResponse struct {
// in:body
Body struct {
// Unique key
Key string ` json:"key" `
// Unique key used to delete the snapshot. It is different from the key so that only the creator can delete the snapshot.
DeleteKey string ` json:"deleteKey" `
URL string ` json:"url" `
DeleteUrl string ` json:"deleteUrl" `
// Snapshot id
ID int64 ` json:"id" `
} ` json:"body" `
}
// swagger:response searchDashboardSnapshotsResponse
type SearchDashboardSnapshotsResponse struct {
// in:body
Body [ ] * dashboardsnapshots . DashboardSnapshotDTO ` json:"body" `
}
// swagger:response getDashboardSnapshotResponse
type GetDashboardSnapshotResponse DashboardResponse
// swagger:response getSharingOptionsResponse
type GetSharingOptionsResponse struct {
// in:body
Body struct {
ExternalSnapshotURL string ` json:"externalSnapshotURL" `
ExternalSnapshotName string ` json:"externalSnapshotName" `
ExternalEnabled bool ` json:"externalEnabled" `
} ` json:"body" `
}