diff --git a/pkg/api/folder.go b/pkg/api/folder.go index 9f554da2c7e..8c0d02742aa 100644 --- a/pkg/api/folder.go +++ b/pkg/api/folder.go @@ -3,8 +3,10 @@ package api import ( "context" "errors" + "fmt" "net/http" "strconv" + "strings" k8sErrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -697,6 +699,7 @@ func (fk8s *folderK8sHandler) createFolder(c *contextmodel.ReqContext) { return } + fk8s.accesscontrolService.ClearUserPermissionCache(c.SignedInUser) folderDTO, err := fk8s.newToFolderDto(c, *out) if err != nil { fk8s.writeError(c, err) @@ -802,6 +805,18 @@ func (fk8s *folderK8sHandler) newToFolderDto(c *contextmodel.ReqContext, item un return dtos.Folder{}, err } + toID := func(rawIdentifier string) (int64, error) { + parts := strings.Split(rawIdentifier, ":") + if len(parts) < 2 { + return 0, fmt.Errorf("invalid user identifier") + } + userID, err := strconv.ParseInt(parts[1], 10, 64) + if err != nil { + return 0, fmt.Errorf("faild to parse user identifier") + } + return userID, nil + } + toDTO := func(f *folder.Folder, checkCanView bool) (dtos.Folder, error) { g, err := guardian.NewByFolder(c.Req.Context(), f, c.SignedInUser.GetOrgID(), c.SignedInUser) if err != nil { @@ -815,11 +830,19 @@ func (fk8s *folderK8sHandler) newToFolderDto(c *contextmodel.ReqContext, item un // Finding creator and last updater of the folder updater, creator := anonString, anonString - if f.CreatedBy > 0 { - creator = fk8s.getUserLogin(ctx, f.CreatedBy) + if len(fDTO.CreatedBy) > 0 { + id, err := toID(fDTO.CreatedBy) + if err != nil { + return dtos.Folder{}, err + } + creator = fk8s.getUserLogin(ctx, id) } - if f.UpdatedBy > 0 { - updater = fk8s.getUserLogin(ctx, f.UpdatedBy) + if len(fDTO.UpdatedBy) > 0 { + id, err := toID(fDTO.UpdatedBy) + if err != nil { + return dtos.Folder{}, err + } + updater = fk8s.getUserLogin(ctx, id) } acMetadata, _ := fk8s.getFolderACMetadata(c, f) diff --git a/pkg/registry/apis/folders/conversions.go b/pkg/registry/apis/folders/conversions.go index 86389ca1434..125e5838a79 100644 --- a/pkg/registry/apis/folders/conversions.go +++ b/pkg/registry/apis/folders/conversions.go @@ -82,7 +82,9 @@ func UnstructuredToLegacyFolderDTO(item unstructured.Unstructured) (*dtos.Folder // avoid panic var createdTime time.Time if created != nil { - createdTime = *created + // #TODO Fix this time format. The legacy time format seems to be along the lines of time.Now() + // which includes a part that represents a fraction of a second. + createdTime = created.Local() } dto := &dtos.Folder{ @@ -93,20 +95,14 @@ func UnstructuredToLegacyFolderDTO(item unstructured.Unstructured) (*dtos.Folder // #TODO add back CreatedBy, UpdatedBy once we figure out how to access userService // to translate user ID into user login. meta.GetCreatedBy() only stores user ID // Could convert meta.GetCreatedBy() return value to a struct--id and name - // CreatedBy: meta.GetCreatedBy(), - // UpdatedBy: meta.GetCreatedBy(), - URL: getURL(meta, title), + CreatedBy: meta.GetCreatedBy(), + UpdatedBy: meta.GetCreatedBy(), + URL: getURL(meta, title), // #TODO get Created in format "2024-09-12T15:37:41.09466+02:00" Created: createdTime, // #TODO figure out whether we want to set "updated" and "updated by". Could replace with // meta.GetUpdatedTimestamp() but it currently gets overwritten in prepareObjectForStorage(). Updated: createdTime, - // #TODO figure out how to set these properly - CanSave: false, - CanEdit: false, - CanAdmin: false, - CanDelete: false, - HasACL: false, // #TODO figure out about adding version, parents, orgID fields } @@ -141,6 +137,9 @@ func convertToK8sResource(v *folder.Folder, namespacer request.NamespaceMapper) Timestamp: &v.Created, }) } + // #TODO: turns out these get overwritten by Unified Storage (see pkg/storage/unified/apistore/prepare.go) + // We're going to have to align with that. For now we do need the user ID because the folder type stores it + // as the only user identifier if v.CreatedBy > 0 { meta.SetCreatedBy(fmt.Sprintf("user:%d", v.CreatedBy)) }