github.com/esnet/gdg@v0.6.1-0.20240412190737-6b6eba9c14d8/internal/service/connection_permissions.go (about) 1 package service 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "log/slog" 8 "path/filepath" 9 "strings" 10 11 "github.com/esnet/gdg/internal/config" 12 "github.com/esnet/gdg/internal/service/filters" 13 "github.com/esnet/gdg/internal/tools" 14 "github.com/gosimple/slug" 15 "github.com/grafana/grafana-openapi-client-go/client/datasource_permissions" 16 "github.com/grafana/grafana-openapi-client-go/models" 17 ) 18 19 // ListConnectionPermissions lists all connection permission matching the given filter 20 func (s *DashNGoImpl) ListConnectionPermissions(filter filters.Filter) map[*models.DataSourceListItemDTO]*models.DataSourcePermissionsDTO { 21 if !s.grafanaConf.IsEnterprise() { 22 log.Fatal("Requires Enterprise to be enabled. Please check your GDG configuration and try again") 23 } 24 result := make(map[*models.DataSourceListItemDTO]*models.DataSourcePermissionsDTO) 25 connections := s.ListConnections(filter) 26 for ndx, connection := range connections { 27 permission, err := s.getConnectionPermission(connection.ID) 28 if err != nil { 29 slog.Error("unable to retrieve connection permissions for ID", "id", connection.ID) 30 continue 31 } 32 result[&connections[ndx]] = permission.GetPayload() 33 34 } 35 36 return result 37 } 38 39 // DownloadConnectionPermissions download permissions to local file system 40 func (s *DashNGoImpl) DownloadConnectionPermissions(filter filters.Filter) []string { 41 slog.Info("Downloading connection permissions") 42 var ( 43 dsPacked []byte 44 err error 45 dataFiles []string 46 ) 47 currentPermissions := s.ListConnectionPermissions(filter) 48 for connection, permission := range currentPermissions { 49 if dsPacked, err = json.MarshalIndent(permission, "", " "); err != nil { 50 slog.Error("unable to marshall json ", "err", err.Error(), "connectionName", connection.Name) 51 continue 52 } 53 dsPath := buildResourcePath(slug.Make(connection.Name), config.ConnectionPermissionResource) 54 if err = s.storage.WriteFile(dsPath, dsPacked); err != nil { 55 slog.Error("unable to write file. ", "filename", slug.Make(connection.Name), "error", err.Error()) 56 } else { 57 dataFiles = append(dataFiles, dsPath) 58 } 59 } 60 return dataFiles 61 } 62 63 // UploadConnectionPermissions upload connection permissions 64 func (s *DashNGoImpl) UploadConnectionPermissions(filter filters.Filter) []string { 65 var ( 66 rawFolder []byte 67 dataFiles []string 68 ) 69 if !s.grafanaConf.IsEnterprise() { 70 log.Fatal("Requires Enterprise to be enabled. Please check your GDG configuration and try again") 71 } 72 73 filesInDir, err := s.storage.FindAllFiles(config.Config().GetDefaultGrafanaConfig().GetPath(config.ConnectionPermissionResource), false) 74 if err != nil { 75 log.Fatalf("Failed to read folders permission imports: %s", err.Error()) 76 } 77 for _, file := range filesInDir { 78 fileLocation := filepath.Join(config.Config().GetDefaultGrafanaConfig().GetPath(config.ConnectionPermissionResource), file) 79 if !filter.ValidateAll(map[filters.FilterType]string{filters.Name: strings.ReplaceAll(file, ".json", "")}) { 80 slog.Debug("File does not match pattern, skipping file", "filename", file) 81 continue 82 } 83 if strings.HasSuffix(file, ".json") { 84 if rawFolder, err = s.storage.ReadFile(fileLocation); err != nil { 85 slog.Error("failed to read file %s", "filename", fileLocation, "err", err) 86 continue 87 } 88 } 89 90 newEntries := new(models.DataSourcePermissionsDTO) 91 err = json.Unmarshal(rawFolder, &newEntries) 92 if err != nil { 93 slog.Warn("Failed to Decode payload for file", "filename", fileLocation) 94 continue 95 } 96 // Get current permissions 97 permissions, err := s.getConnectionPermission(newEntries.DatasourceID) 98 if err != nil { 99 slog.Error("connection permission could not be retrieved, cannot update permissions") 100 continue 101 } 102 103 success := true 104 // Delete datasource Permissions 105 for _, p := range permissions.GetPayload().Permissions { 106 success = s.deleteConnectionPermission(p.ID, newEntries.DatasourceID) 107 } 108 109 if !success { 110 slog.Error("Failed to delete previous data, cannot update permissions") 111 continue 112 } 113 114 for _, entry := range newEntries.Permissions { 115 p := datasource_permissions.NewAddPermissionParams() 116 p.SetUserID(tools.PtrOf(entry.UserID)) 117 p.SetDatasourceID(fmt.Sprintf("%d", entry.DatasourceID)) 118 p.SetTeamID(tools.PtrOf(entry.TeamID)) 119 p.SetPermission(tools.PtrOf(int64(entry.Permission))) 120 if entry.BuiltInRole != "" { 121 p.SetBuiltinRole(tools.PtrOf(entry.BuiltInRole)) 122 } 123 _, err = s.GetClient().DatasourcePermissions.AddPermission(p) 124 if err != nil { 125 slog.Error("Failed to update folder permissions") 126 } else { 127 dataFiles = append(dataFiles, fileLocation) 128 } 129 } 130 } 131 132 slog.Info("Removing all previous permissions and re-applying") 133 return dataFiles 134 } 135 136 // DeleteAllConnectionPermissions clear all non-default permissions from all connections 137 func (s *DashNGoImpl) DeleteAllConnectionPermissions(filter filters.Filter) []string { 138 dataSources := make([]string, 0) 139 connectionPermissions := s.ListConnectionPermissions(filter) 140 for key, connection := range connectionPermissions { 141 success := true 142 for _, p := range connection.Permissions { 143 res := s.deleteConnectionPermission(p.ID, connection.DatasourceID) 144 if !res { 145 success = false 146 } 147 } 148 if success { 149 dataSources = append(dataSources, key.Name) 150 } 151 } 152 153 return dataSources 154 } 155 156 // deleteConnectionPermission delete a given permission associated with a given datasourceId 157 func (s *DashNGoImpl) deleteConnectionPermission(permissionId int64, datasourceId int64) bool { 158 permissionIdStr := fmt.Sprintf("%d", permissionId) 159 connectionId := fmt.Sprintf("%d", datasourceId) 160 resp, err := s.GetClient().DatasourcePermissions.DeletePermissions(permissionIdStr, connectionId) 161 if err != nil { 162 return false 163 } 164 slog.Debug("permission has been removed associated with datasource %d: %s", "permissionId", permissionId, "datasourceId", datasourceId, "response", resp.GetPayload().Message) 165 return true 166 } 167 168 // getConnectionPermission Get all permissions for a given connection 169 func (s *DashNGoImpl) getConnectionPermission(id int64) (*datasource_permissions.GetAllPermissionsOK, error) { 170 return s.GetClient().DatasourcePermissions.GetAllPermissions(fmt.Sprintf("%d", id)) 171 }