2018-01-29 06:51:01 -06:00
package api
import (
2020-07-23 01:15:47 -05:00
"errors"
2018-02-21 09:38:09 -06:00
"fmt"
2018-01-29 06:51:01 -06:00
"github.com/grafana/grafana/pkg/api/dtos"
2021-01-15 07:43:20 -06:00
"github.com/grafana/grafana/pkg/api/response"
2020-03-04 05:57:20 -06:00
"github.com/grafana/grafana/pkg/models"
2018-01-29 06:51:01 -06:00
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/guardian"
2021-05-12 01:48:17 -05:00
"github.com/grafana/grafana/pkg/services/libraryelements"
2018-01-29 06:51:01 -06:00
"github.com/grafana/grafana/pkg/util"
)
2021-03-17 10:06:10 -05:00
func ( hs * HTTPServer ) GetFolders ( c * models . ReqContext ) response . Response {
s := dashboards . NewFolderService ( c . OrgId , c . SignedInUser , hs . SQLStore )
2019-04-17 06:07:50 -05:00
folders , err := s . GetFolders ( c . QueryInt64 ( "limit" ) )
2018-01-29 06:51:01 -06:00
if err != nil {
2021-04-15 07:54:37 -05:00
return ToFolderErrorResponse ( err )
2018-01-29 06:51:01 -06:00
}
2018-02-20 06:57:32 -06:00
result := make ( [ ] dtos . FolderSearchHit , 0 )
2018-01-29 06:51:01 -06:00
2018-02-20 06:57:32 -06:00
for _ , f := range folders {
result = append ( result , dtos . FolderSearchHit {
Id : f . Id ,
Uid : f . Uid ,
Title : f . Title ,
} )
2018-01-29 06:51:01 -06:00
}
2021-01-15 07:43:20 -06:00
return response . JSON ( 200 , result )
2018-01-29 06:51:01 -06:00
}
2021-03-17 10:06:10 -05:00
func ( hs * HTTPServer ) GetFolderByUID ( c * models . ReqContext ) response . Response {
s := dashboards . NewFolderService ( c . OrgId , c . SignedInUser , hs . SQLStore )
2018-03-22 16:13:46 -05:00
folder , err := s . GetFolderByUID ( c . Params ( ":uid" ) )
2018-02-20 06:57:32 -06:00
if err != nil {
2021-04-15 07:54:37 -05:00
return ToFolderErrorResponse ( err )
2018-01-29 06:51:01 -06:00
}
2018-02-20 06:57:32 -06:00
g := guardian . New ( folder . Id , c . OrgId , c . SignedInUser )
2021-01-15 07:43:20 -06:00
return response . JSON ( 200 , toFolderDto ( g , folder ) )
2018-02-20 06:57:32 -06:00
}
2018-01-29 06:51:01 -06:00
2021-03-17 10:06:10 -05:00
func ( hs * HTTPServer ) GetFolderByID ( c * models . ReqContext ) response . Response {
s := dashboards . NewFolderService ( c . OrgId , c . SignedInUser , hs . SQLStore )
2018-03-22 16:13:46 -05:00
folder , err := s . GetFolderByID ( c . ParamsInt64 ( ":id" ) )
2018-01-29 06:51:01 -06:00
if err != nil {
2021-04-15 07:54:37 -05:00
return ToFolderErrorResponse ( err )
2018-01-29 06:51:01 -06:00
}
2018-02-20 06:57:32 -06:00
g := guardian . New ( folder . Id , c . OrgId , c . SignedInUser )
2021-01-15 07:43:20 -06:00
return response . JSON ( 200 , toFolderDto ( g , folder ) )
2018-02-20 06:57:32 -06:00
}
2018-01-29 06:51:01 -06:00
2021-01-15 07:43:20 -06:00
func ( hs * HTTPServer ) CreateFolder ( c * models . ReqContext , cmd models . CreateFolderCommand ) response . Response {
2021-03-17 10:06:10 -05:00
s := dashboards . NewFolderService ( c . OrgId , c . SignedInUser , hs . SQLStore )
folder , err := s . CreateFolder ( cmd . Title , cmd . Uid )
2018-01-29 06:51:01 -06:00
if err != nil {
2021-04-15 07:54:37 -05:00
return ToFolderErrorResponse ( err )
2018-01-29 06:51:01 -06:00
}
2019-03-12 01:32:47 -05:00
if hs . Cfg . EditorsCanAdmin {
2021-03-17 10:06:10 -05:00
if err := s . MakeUserAdmin ( c . OrgId , c . SignedInUser . UserId , folder . Id , true ) ; err != nil {
hs . log . Error ( "Could not make user admin" , "folder" , folder . Title , "user" ,
c . SignedInUser . UserId , "error" , err )
2019-03-11 09:05:28 -05:00
}
2019-03-05 09:53:16 -06:00
}
2021-03-17 10:06:10 -05:00
g := guardian . New ( folder . Id , c . OrgId , c . SignedInUser )
return response . JSON ( 200 , toFolderDto ( g , folder ) )
2018-01-29 06:51:01 -06:00
}
2021-03-17 10:06:10 -05:00
func ( hs * HTTPServer ) UpdateFolder ( c * models . ReqContext , cmd models . UpdateFolderCommand ) response . Response {
s := dashboards . NewFolderService ( c . OrgId , c . SignedInUser , hs . SQLStore )
2018-02-20 06:57:32 -06:00
err := s . UpdateFolder ( c . Params ( ":uid" ) , & cmd )
2018-01-29 06:51:01 -06:00
if err != nil {
2021-04-15 07:54:37 -05:00
return ToFolderErrorResponse ( err )
2018-01-29 06:51:01 -06:00
}
2018-02-20 06:57:32 -06:00
g := guardian . New ( cmd . Result . Id , c . OrgId , c . SignedInUser )
2021-01-15 07:43:20 -06:00
return response . JSON ( 200 , toFolderDto ( g , cmd . Result ) )
2018-01-29 06:51:01 -06:00
}
2021-03-02 03:34:01 -06:00
func ( hs * HTTPServer ) DeleteFolder ( c * models . ReqContext ) response . Response { // temporarily adding this function to HTTPServer, will be removed from HTTPServer when librarypanels featuretoggle is removed
2021-03-17 10:06:10 -05:00
s := dashboards . NewFolderService ( c . OrgId , c . SignedInUser , hs . SQLStore )
2021-05-12 01:48:17 -05:00
err := hs . LibraryElementService . DeleteLibraryElementsInFolder ( c , c . Params ( ":uid" ) )
if err != nil {
if errors . Is ( err , libraryelements . ErrFolderHasConnectedLibraryElements ) {
return response . Error ( 403 , "Folder could not be deleted because it contains library elements in use" , err )
2021-03-02 03:34:01 -06:00
}
2021-05-12 01:48:17 -05:00
return ToFolderErrorResponse ( err )
2021-03-02 03:34:01 -06:00
}
2018-02-20 06:57:32 -06:00
f , err := s . DeleteFolder ( c . Params ( ":uid" ) )
if err != nil {
2021-04-15 07:54:37 -05:00
return ToFolderErrorResponse ( err )
2018-01-29 06:51:01 -06:00
}
2021-01-15 07:43:20 -06:00
return response . JSON ( 200 , util . DynMap {
2018-02-21 09:38:09 -06:00
"title" : f . Title ,
"message" : fmt . Sprintf ( "Folder %s deleted" , f . Title ) ,
2020-07-31 01:22:09 -05:00
"id" : f . Id ,
2018-02-21 09:38:09 -06:00
} )
2018-01-29 06:51:01 -06:00
}
2020-03-04 05:57:20 -06:00
func toFolderDto ( g guardian . DashboardGuardian , folder * models . Folder ) dtos . Folder {
2018-02-19 06:32:45 -06:00
canEdit , _ := g . CanEdit ( )
canSave , _ := g . CanSave ( )
canAdmin , _ := g . CanAdmin ( )
2018-01-29 06:51:01 -06:00
// Finding creator and last updater of the folder
2018-09-22 03:50:00 -05:00
updater , creator := anonString , anonString
2018-01-29 06:51:01 -06:00
if folder . CreatedBy > 0 {
creator = getUserLogin ( folder . CreatedBy )
}
2018-02-01 14:00:37 -06:00
if folder . UpdatedBy > 0 {
updater = getUserLogin ( folder . UpdatedBy )
}
2018-01-29 06:51:01 -06:00
return dtos . Folder {
Id : folder . Id ,
2018-02-01 14:00:37 -06:00
Uid : folder . Uid ,
2018-01-29 06:51:01 -06:00
Title : folder . Title ,
2018-02-20 06:57:32 -06:00
Url : folder . Url ,
2018-01-29 06:51:01 -06:00
HasAcl : folder . HasAcl ,
CanSave : canSave ,
CanEdit : canEdit ,
CanAdmin : canAdmin ,
CreatedBy : creator ,
Created : folder . Created ,
UpdatedBy : updater ,
Updated : folder . Updated ,
Version : folder . Version ,
}
}
2021-04-15 07:54:37 -05:00
// ToFolderErrorResponse returns a different response status according to the folder error type
func ToFolderErrorResponse ( err error ) response . Response {
2020-07-23 01:15:47 -05:00
var dashboardErr models . DashboardErr
if ok := errors . As ( err , & dashboardErr ) ; ok {
2021-01-15 07:43:20 -06:00
return response . Error ( dashboardErr . StatusCode , err . Error ( ) , err )
2020-07-23 01:15:47 -05:00
}
2020-11-19 06:34:28 -06:00
if errors . Is ( err , models . ErrFolderTitleEmpty ) ||
errors . Is ( err , models . ErrFolderSameNameExists ) ||
errors . Is ( err , models . ErrFolderWithSameUIDExists ) ||
errors . Is ( err , models . ErrDashboardTypeMismatch ) ||
errors . Is ( err , models . ErrDashboardInvalidUid ) ||
errors . Is ( err , models . ErrDashboardUidTooLong ) {
2021-01-15 07:43:20 -06:00
return response . Error ( 400 , err . Error ( ) , nil )
2018-01-29 06:51:01 -06:00
}
2020-11-19 06:34:28 -06:00
if errors . Is ( err , models . ErrFolderAccessDenied ) {
2021-01-15 07:43:20 -06:00
return response . Error ( 403 , "Access denied" , err )
2018-02-20 06:57:32 -06:00
}
2020-11-19 06:34:28 -06:00
if errors . Is ( err , models . ErrFolderNotFound ) {
2021-01-15 07:43:20 -06:00
return response . JSON ( 404 , util . DynMap { "status" : "not-found" , "message" : models . ErrFolderNotFound . Error ( ) } )
2018-01-29 06:51:01 -06:00
}
2020-11-19 06:34:28 -06:00
if errors . Is ( err , models . ErrFolderVersionMismatch ) {
2021-01-15 07:43:20 -06:00
return response . JSON ( 412 , util . DynMap { "status" : "version-mismatch" , "message" : models . ErrFolderVersionMismatch . Error ( ) } )
2018-02-01 11:29:00 -06:00
}
2021-01-15 07:43:20 -06:00
return response . Error ( 500 , "Folder API error" , err )
2018-01-29 06:51:01 -06:00
}