2022-01-28 10:55:09 -06:00
package queryhistory
import (
"net/http"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models"
2022-04-29 02:55:33 -05:00
"github.com/grafana/grafana/pkg/tsdb/legacydata"
2022-02-04 09:14:36 -06:00
"github.com/grafana/grafana/pkg/util"
2022-01-28 10:55:09 -06:00
"github.com/grafana/grafana/pkg/web"
)
func ( s * QueryHistoryService ) registerAPIEndpoints ( ) {
s . RouteRegister . Group ( "/api/query-history" , func ( entities routing . RouteRegister ) {
entities . Post ( "/" , middleware . ReqSignedIn , routing . Wrap ( s . createHandler ) )
2022-03-07 05:28:04 -06:00
entities . Get ( "/" , middleware . ReqSignedIn , routing . Wrap ( s . searchHandler ) )
2022-02-04 09:14:36 -06:00
entities . Delete ( "/:uid" , middleware . ReqSignedIn , routing . Wrap ( s . deleteHandler ) )
2022-02-23 10:03:04 -06:00
entities . Post ( "/star/:uid" , middleware . ReqSignedIn , routing . Wrap ( s . starHandler ) )
entities . Delete ( "/star/:uid" , middleware . ReqSignedIn , routing . Wrap ( s . unstarHandler ) )
2022-02-15 08:43:17 -06:00
entities . Patch ( "/:uid" , middleware . ReqSignedIn , routing . Wrap ( s . patchCommentHandler ) )
2022-04-14 02:33:41 -05:00
// Remove migrate endpoint in Grafana v10 as breaking change
entities . Post ( "/migrate" , middleware . ReqSignedIn , routing . Wrap ( s . migrateHandler ) )
2022-01-28 10:55:09 -06:00
} )
}
2022-07-27 08:54:37 -05:00
// swagger:route POST /query-history query_history createQuery
//
// Add query to query history.
//
// Adds new query to query history.
//
// Responses:
// 200: getQueryHistoryResponse
// 400: badRequestError
// 401: unauthorisedError
// 500: internalServerError
2022-01-28 10:55:09 -06:00
func ( s * QueryHistoryService ) createHandler ( c * models . ReqContext ) response . Response {
cmd := CreateQueryInQueryHistoryCommand { }
if err := web . Bind ( c . Req , & cmd ) ; err != nil {
return response . Error ( http . StatusBadRequest , "bad request data" , err )
}
2022-02-04 09:14:36 -06:00
query , err := s . CreateQueryInQueryHistory ( c . Req . Context ( ) , c . SignedInUser , cmd )
2022-01-28 10:55:09 -06:00
if err != nil {
2022-02-04 09:14:36 -06:00
return response . Error ( http . StatusInternalServerError , "Failed to create query history" , err )
2022-01-28 10:55:09 -06:00
}
2022-02-04 09:14:36 -06:00
return response . JSON ( http . StatusOK , QueryHistoryResponse { Result : query } )
}
2022-07-27 08:54:37 -05:00
// swagger:route GET /query-history query_history searchQueries
//
// Query history search.
//
// Returns a list of queries in the query history that matches the search criteria.
// Query history search supports pagination. Use the `limit` parameter to control the maximum number of queries returned; the default limit is 100.
// You can also use the `page` query parameter to fetch queries from any page other than the first one.
//
// Responses:
// 200: getQueryHistorySearchResponse
// 401: unauthorisedError
// 500: internalServerError
2022-03-07 05:28:04 -06:00
func ( s * QueryHistoryService ) searchHandler ( c * models . ReqContext ) response . Response {
2022-04-29 02:55:33 -05:00
timeRange := legacydata . NewDataTimeRange ( c . Query ( "from" ) , c . Query ( "to" ) )
2022-03-07 05:28:04 -06:00
query := SearchInQueryHistoryQuery {
DatasourceUIDs : c . QueryStrings ( "datasourceUid" ) ,
SearchString : c . Query ( "searchString" ) ,
OnlyStarred : c . QueryBoolWithDefault ( "onlyStarred" , false ) ,
Sort : c . Query ( "sort" ) ,
Page : c . QueryInt ( "page" ) ,
Limit : c . QueryInt ( "limit" ) ,
2022-04-29 02:55:33 -05:00
From : timeRange . GetFromAsSecondsEpoch ( ) ,
To : timeRange . GetToAsSecondsEpoch ( ) ,
2022-03-07 05:28:04 -06:00
}
result , err := s . SearchInQueryHistory ( c . Req . Context ( ) , c . SignedInUser , query )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Failed to get query history" , err )
}
return response . JSON ( http . StatusOK , QueryHistorySearchResponse { Result : result } )
}
2022-07-27 08:54:37 -05:00
// swagger:route DELETE /query-history/{query_history_uid} query_history deleteQuery
//
// Delete query in query history.
//
// Deletes an existing query in query history as specified by the UID. This operation cannot be reverted.
//
// Responses:
// 200: getQueryHistoryDeleteQueryResponse
// 401: unauthorisedError
// 500: internalServerError
2022-02-04 09:14:36 -06:00
func ( s * QueryHistoryService ) deleteHandler ( c * models . ReqContext ) response . Response {
queryUID := web . Params ( c . Req ) [ ":uid" ]
2022-02-23 10:03:04 -06:00
if len ( queryUID ) > 0 && ! util . IsValidShortUID ( queryUID ) {
2022-02-04 09:14:36 -06:00
return response . Error ( http . StatusNotFound , "Query in query history not found" , nil )
}
id , err := s . DeleteQueryFromQueryHistory ( c . Req . Context ( ) , c . SignedInUser , queryUID )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Failed to delete query from query history" , err )
}
2022-06-13 02:47:40 -05:00
return response . JSON ( http . StatusOK , QueryHistoryDeleteQueryResponse {
2022-02-04 09:14:36 -06:00
Message : "Query deleted" ,
ID : id ,
} )
2022-01-28 10:55:09 -06:00
}
2022-02-15 08:43:17 -06:00
2022-07-27 08:54:37 -05:00
// swagger:route PATCH /query-history/{query_history_uid} query_history patchQueryComment
//
// Update comment for query in query history.
//
// Updates comment for query in query history as specified by the UID.
//
// Responses:
// 200: getQueryHistoryResponse
// 400: badRequestError
// 401: unauthorisedError
// 500: internalServerError
2022-02-15 08:43:17 -06:00
func ( s * QueryHistoryService ) patchCommentHandler ( c * models . ReqContext ) response . Response {
queryUID := web . Params ( c . Req ) [ ":uid" ]
2022-02-23 10:03:04 -06:00
if len ( queryUID ) > 0 && ! util . IsValidShortUID ( queryUID ) {
2022-02-15 08:43:17 -06:00
return response . Error ( http . StatusNotFound , "Query in query history not found" , nil )
}
cmd := PatchQueryCommentInQueryHistoryCommand { }
if err := web . Bind ( c . Req , & cmd ) ; err != nil {
return response . Error ( http . StatusBadRequest , "bad request data" , err )
}
query , err := s . PatchQueryCommentInQueryHistory ( c . Req . Context ( ) , c . SignedInUser , queryUID , cmd )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Failed to update comment of query in query history" , err )
}
return response . JSON ( http . StatusOK , QueryHistoryResponse { Result : query } )
}
2022-02-23 10:03:04 -06:00
2022-07-27 08:54:37 -05:00
// swagger:route POST /query-history/star/{query_history_uid} query_history starQuery
//
// Add star to query in query history.
//
// Adds star to query in query history as specified by the UID.
//
// Responses:
// 200: getQueryHistoryResponse
// 401: unauthorisedError
// 500: internalServerError
2022-02-23 10:03:04 -06:00
func ( s * QueryHistoryService ) starHandler ( c * models . ReqContext ) response . Response {
queryUID := web . Params ( c . Req ) [ ":uid" ]
if len ( queryUID ) > 0 && ! util . IsValidShortUID ( queryUID ) {
return response . Error ( http . StatusNotFound , "Query in query history not found" , nil )
}
query , err := s . StarQueryInQueryHistory ( c . Req . Context ( ) , c . SignedInUser , queryUID )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Failed to star query in query history" , err )
}
return response . JSON ( http . StatusOK , QueryHistoryResponse { Result : query } )
}
2022-07-27 08:54:37 -05:00
// swagger:route DELETE /query-history/star/{query_history_uid} query_history unstarQuery
//
// Remove star to query in query history.
//
// Removes star from query in query history as specified by the UID.
//
// Responses:
// 200: getQueryHistoryResponse
// 401: unauthorisedError
// 500: internalServerError
2022-02-23 10:03:04 -06:00
func ( s * QueryHistoryService ) unstarHandler ( c * models . ReqContext ) response . Response {
queryUID := web . Params ( c . Req ) [ ":uid" ]
if len ( queryUID ) > 0 && ! util . IsValidShortUID ( queryUID ) {
return response . Error ( http . StatusNotFound , "Query in query history not found" , nil )
}
query , err := s . UnstarQueryInQueryHistory ( c . Req . Context ( ) , c . SignedInUser , queryUID )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Failed to unstar query in query history" , err )
}
return response . JSON ( http . StatusOK , QueryHistoryResponse { Result : query } )
}
2022-04-14 02:33:41 -05:00
2022-07-27 08:54:37 -05:00
// swagger:route POST /query-history/migrate query_history migrateQueries
//
// Migrate queries to query history.
//
// Adds multiple queries to query history.
//
// Responses:
// 200: getQueryHistoryMigrationResponse
// 400: badRequestError
// 401: unauthorisedError
// 500: internalServerError
2022-04-14 02:33:41 -05:00
func ( s * QueryHistoryService ) migrateHandler ( c * models . ReqContext ) response . Response {
cmd := MigrateQueriesToQueryHistoryCommand { }
if err := web . Bind ( c . Req , & cmd ) ; err != nil {
return response . Error ( http . StatusBadRequest , "bad request data" , err )
}
totalCount , starredCount , err := s . MigrateQueriesToQueryHistory ( c . Req . Context ( ) , c . SignedInUser , cmd )
if err != nil {
return response . Error ( http . StatusInternalServerError , "Failed to migrate query history" , err )
}
return response . JSON ( http . StatusOK , QueryHistoryMigrationResponse { Message : "Query history successfully migrated" , TotalCount : totalCount , StarredCount : starredCount } )
}
2022-07-27 08:54:37 -05:00
// swagger:parameters starQuery patchQueryComment deleteQuery unstarQuery
type QueryHistoryByUID struct {
// in:path
// required:true
UID string ` json:"query_history_uid" `
}
// swagger:parameters searchQueries
type SearchQueriesParams struct {
// List of data source UIDs to search for
// in:query
// required: false
// type: array
// collectionFormat: multi
DatasourceUid [ ] string ` json:"datasourceUid" `
// Text inside query or comments that is searched for
// in:query
// required: false
SearchString string ` json:"searchString" `
// Flag indicating if only starred queries should be returned
// in:query
// required: false
OnlyStarred bool ` json:"onlyStarred" `
// Sort method
// in:query
// required: false
// default: time-desc
// Enum: time-desc,time-asc
Sort string ` json:"sort" `
// Use this parameter to access hits beyond limit. Numbering starts at 1. limit param acts as page size.
// in:query
// required: false
Page int ` json:"page" `
// Limit the number of returned results
// in:query
// required: false
Limit int ` json:"limit" `
// From range for the query history search
// in:query
// required: false
From int64 ` json:"from" `
// To range for the query history search
// in:query
// required: false
To int64 ` json:"to" `
}
// swagger:parameters createQuery
type CreateQueryParams struct {
// in:body
// required:true
Body CreateQueryInQueryHistoryCommand ` json:"body" `
}
// swagger:parameters patchQueryComment
type PatchQueryCommentParams struct {
// in:body
// required:true
Body PatchQueryCommentInQueryHistoryCommand ` json:"body" `
}
// swagger:parameters migrateQueries
type MigrateQueriesParams struct {
// in:body
// required:true
Body MigrateQueriesToQueryHistoryCommand ` json:"body" `
}
//swagger:response getQueryHistorySearchResponse
type GetQueryHistorySearchResponse struct {
// in: body
Body QueryHistorySearchResponse ` json:"body" `
}
// swagger:response getQueryHistoryResponse
type GetQueryHistoryResponse struct {
// in: body
Body QueryHistoryResponse ` json:"body" `
}
// swagger:response getQueryHistoryDeleteQueryResponse
type GetQueryHistoryDeleteQueryResponse struct {
// in: body
Body QueryHistoryDeleteQueryResponse ` json:"body" `
}
// swagger:response getQueryHistoryMigrationResponse
type GetQueryHistoryMigrationResponse struct {
// in: body
Body QueryHistoryMigrationResponse ` json:"body" `
}