From 000c99c63b14c3cec3722a8e18a4831b9d210cae Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Tue, 1 Sep 2026 13:16:01 +0200 Subject: [PATCH] graph: expose pendingOperations on driveItems --- go.mod | 2 +- go.sum | 2 + services/graph/pkg/service/v0/driveitems.go | 7 + .../graph/pkg/service/v0/driveitems_test.go | 21 +++ .../opencloud-eu/libre-graph-api-go/README.md | 2 + .../libre-graph-api-go/model_drive_item.go | 36 +++++ .../model_pending_operations.go | 126 +++++++++++++++++ ...nding_operations_pending_content_update.go | 128 ++++++++++++++++++ vendor/modules.txt | 2 +- 9 files changed, 324 insertions(+), 2 deletions(-) create mode 100644 vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations.go create mode 100644 vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations_pending_content_update.go diff --git a/go.mod b/go.mod index b609e9ef20..62340fb4b2 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,7 @@ require ( github.com/onsi/gomega v1.42.1 github.com/open-policy-agent/opa v1.19.1 github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 - github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55 + github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d github.com/opencloud-eu/reva/v2 v2.49.0 github.com/opensearch-project/opensearch-go/v4 v4.7.3 github.com/orcaman/concurrent-map v1.0.0 diff --git a/go.sum b/go.sum index 6ffc6d9bba..748288854d 100644 --- a/go.sum +++ b/go.sum @@ -942,6 +942,8 @@ github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+l github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI= github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55 h1:dzYZ5iA6i0QoFUap9l6sZ4Ts2HXiXVfsOoiRYToYgm8= github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55/go.mod h1:lTM8JeGblNpoMySTW7Lui2+c5TTLI95mwxtdUIHHrhU= +github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d h1:3zbb31655ZvqwLMWMIiUAhYer6YcFnv/oguujnX7aOU= +github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d/go.mod h1:lTM8JeGblNpoMySTW7Lui2+c5TTLI95mwxtdUIHHrhU= github.com/opencloud-eu/reva/v2 v2.49.0 h1:AwECMDDth3NUaihZRf9bI9HNpWutvaRijOCvQyQfTT4= github.com/opencloud-eu/reva/v2 v2.49.0/go.mod h1:Frg+UWnVcSy+412UB3l2LcD0KY8ZNu1samimwkNywbg= github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4 h1:l2oB/RctH+t8r7QBj5p8thfEHCM/jF35aAY3WQ3hADI= diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index 51e6a2a7f3..b2c21017cb 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -490,6 +490,13 @@ func cs3ResourceToDriveItem(logger *log.Logger, publicBaseURL *url.URL, res *sto } } + if utils.IsProcessing(res) { + // queuedDateTime stays absent, we do not track when postprocessing started + driveItem.PendingOperations = &libregraph.PendingOperations{ + PendingContentUpdate: &libregraph.PendingOperationsPendingContentUpdate{}, + } + } + return driveItem, nil } diff --git a/services/graph/pkg/service/v0/driveitems_test.go b/services/graph/pkg/service/v0/driveitems_test.go index b588638589..db2ab7bf44 100644 --- a/services/graph/pkg/service/v0/driveitems_test.go +++ b/services/graph/pkg/service/v0/driveitems_test.go @@ -333,6 +333,27 @@ var _ = Describe("Driveitems", func() { Expect(res.Value[0].Location).To(BeNil()) Expect(res.Value[0].LibreGraphMeFollowing).To(BeNil()) Expect(res.Value[0].LibreGraphTags).To(BeNil()) + Expect(res.Value[0].PendingOperations).To(BeNil()) + }) + + It("reports a pending content update while the item is being processed", func() { + gatewayClient.On("ListContainer", mock.Anything, mock.Anything).Return(&provider.ListContainerResponse{ + Status: status.NewOK(ctx), + Infos: []*provider.ResourceInfo{ + { + Type: provider.ResourceType_RESOURCE_TYPE_FILE, + Id: &provider.ResourceId{StorageId: "storageid", SpaceId: "spaceid", OpaqueId: "opaqueid"}, + Etag: "etag", + Mtime: utils.TimeToTS(mtime), + Opaque: utils.AppendPlainToOpaque(nil, "status", "processing"), + }, + }, + }, nil) + + res := assertItemsList(1) + Expect(res.Value[0].PendingOperations).ToNot(BeNil()) + Expect(res.Value[0].PendingOperations.PendingContentUpdate).ToNot(BeNil()) + Expect(res.Value[0].PendingOperations.PendingContentUpdate.QueuedDateTime).To(BeNil()) }) It("returns tags if metadata is available", func() { diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md b/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md index eadd712142..816ad6e916 100644 --- a/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md @@ -242,6 +242,8 @@ Class | Method | HTTP request | Description - [OpenGraphFile](docs/OpenGraphFile.md) - [PasswordChange](docs/PasswordChange.md) - [PasswordProfile](docs/PasswordProfile.md) + - [PendingOperations](docs/PendingOperations.md) + - [PendingOperationsPendingContentUpdate](docs/PendingOperationsPendingContentUpdate.md) - [Permission](docs/Permission.md) - [Photo](docs/Photo.md) - [Quota](docs/Quota.md) diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go index a9a901a0c0..bf74ea8963 100644 --- a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go @@ -42,6 +42,7 @@ type DriveItem struct { // An eTag for the content of the item. This eTag is not changed if only the metadata is changed. Note This property is not returned if the item is a folder. Read-only. CTag *string `json:"cTag,omitempty"` Deleted *Deleted `json:"deleted,omitempty"` + PendingOperations *PendingOperations `json:"pendingOperations,omitempty"` File *OpenGraphFile `json:"file,omitempty"` FileSystemInfo *FileSystemInfo `json:"fileSystemInfo,omitempty"` Folder *Folder `json:"folder,omitempty"` @@ -514,6 +515,38 @@ func (o *DriveItem) SetDeleted(v Deleted) { o.Deleted = &v } +// GetPendingOperations returns the PendingOperations field value if set, zero value otherwise. +func (o *DriveItem) GetPendingOperations() PendingOperations { + if o == nil || IsNil(o.PendingOperations) { + var ret PendingOperations + return ret + } + return *o.PendingOperations +} + +// GetPendingOperationsOk returns a tuple with the PendingOperations field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DriveItem) GetPendingOperationsOk() (*PendingOperations, bool) { + if o == nil || IsNil(o.PendingOperations) { + return nil, false + } + return o.PendingOperations, true +} + +// HasPendingOperations returns a boolean if a field has been set. +func (o *DriveItem) HasPendingOperations() bool { + if o != nil && !IsNil(o.PendingOperations) { + return true + } + + return false +} + +// SetPendingOperations gets a reference to the given PendingOperations and assigns it to the PendingOperations field. +func (o *DriveItem) SetPendingOperations(v PendingOperations) { + o.PendingOperations = &v +} + // GetFile returns the File field value if set, zero value otherwise. func (o *DriveItem) GetFile() OpenGraphFile { if o == nil || IsNil(o.File) { @@ -1363,6 +1396,9 @@ func (o DriveItem) ToMap() (map[string]interface{}, error) { if !IsNil(o.Deleted) { toSerialize["deleted"] = o.Deleted } + if !IsNil(o.PendingOperations) { + toSerialize["pendingOperations"] = o.PendingOperations + } if !IsNil(o.File) { toSerialize["file"] = o.File } diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations.go new file mode 100644 index 0000000000..87f2c85dbb --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations.go @@ -0,0 +1,126 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" +) + +// checks if the PendingOperations type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &PendingOperations{} + +// PendingOperations Present while operations affecting the item's content have not completed, whether still queued or already running. While present, requests for the item's content fail, the content is withheld until processing completes and the facet disappears. +type PendingOperations struct { + PendingContentUpdate *PendingOperationsPendingContentUpdate `json:"pendingContentUpdate,omitempty"` +} + +// NewPendingOperations instantiates a new PendingOperations object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPendingOperations() *PendingOperations { + this := PendingOperations{} + return &this +} + +// NewPendingOperationsWithDefaults instantiates a new PendingOperations object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPendingOperationsWithDefaults() *PendingOperations { + this := PendingOperations{} + return &this +} + +// GetPendingContentUpdate returns the PendingContentUpdate field value if set, zero value otherwise. +func (o *PendingOperations) GetPendingContentUpdate() PendingOperationsPendingContentUpdate { + if o == nil || IsNil(o.PendingContentUpdate) { + var ret PendingOperationsPendingContentUpdate + return ret + } + return *o.PendingContentUpdate +} + +// GetPendingContentUpdateOk returns a tuple with the PendingContentUpdate field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PendingOperations) GetPendingContentUpdateOk() (*PendingOperationsPendingContentUpdate, bool) { + if o == nil || IsNil(o.PendingContentUpdate) { + return nil, false + } + return o.PendingContentUpdate, true +} + +// HasPendingContentUpdate returns a boolean if a field has been set. +func (o *PendingOperations) HasPendingContentUpdate() bool { + if o != nil && !IsNil(o.PendingContentUpdate) { + return true + } + + return false +} + +// SetPendingContentUpdate gets a reference to the given PendingOperationsPendingContentUpdate and assigns it to the PendingContentUpdate field. +func (o *PendingOperations) SetPendingContentUpdate(v PendingOperationsPendingContentUpdate) { + o.PendingContentUpdate = &v +} + +func (o PendingOperations) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o PendingOperations) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.PendingContentUpdate) { + toSerialize["pendingContentUpdate"] = o.PendingContentUpdate + } + return toSerialize, nil +} + +type NullablePendingOperations struct { + value *PendingOperations + isSet bool +} + +func (v NullablePendingOperations) Get() *PendingOperations { + return v.value +} + +func (v *NullablePendingOperations) Set(val *PendingOperations) { + v.value = val + v.isSet = true +} + +func (v NullablePendingOperations) IsSet() bool { + return v.isSet +} + +func (v *NullablePendingOperations) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePendingOperations(val *PendingOperations) *NullablePendingOperations { + return &NullablePendingOperations{value: val, isSet: true} +} + +func (v NullablePendingOperations) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePendingOperations) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations_pending_content_update.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations_pending_content_update.go new file mode 100644 index 0000000000..87df076384 --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_pending_operations_pending_content_update.go @@ -0,0 +1,128 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" + "time" +) + +// checks if the PendingOperationsPendingContentUpdate type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &PendingOperationsPendingContentUpdate{} + +// PendingOperationsPendingContentUpdate An update to the item's content has not completed, for example post-processing such as virus scanning after an upload. MS Graph does not specify how reads behave while this is present; in OpenCloud content requests fail. +type PendingOperationsPendingContentUpdate struct { + // Time the operation was queued. May be absent. Read-only. + QueuedDateTime *time.Time `json:"queuedDateTime,omitempty"` +} + +// NewPendingOperationsPendingContentUpdate instantiates a new PendingOperationsPendingContentUpdate object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPendingOperationsPendingContentUpdate() *PendingOperationsPendingContentUpdate { + this := PendingOperationsPendingContentUpdate{} + return &this +} + +// NewPendingOperationsPendingContentUpdateWithDefaults instantiates a new PendingOperationsPendingContentUpdate object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPendingOperationsPendingContentUpdateWithDefaults() *PendingOperationsPendingContentUpdate { + this := PendingOperationsPendingContentUpdate{} + return &this +} + +// GetQueuedDateTime returns the QueuedDateTime field value if set, zero value otherwise. +func (o *PendingOperationsPendingContentUpdate) GetQueuedDateTime() time.Time { + if o == nil || IsNil(o.QueuedDateTime) { + var ret time.Time + return ret + } + return *o.QueuedDateTime +} + +// GetQueuedDateTimeOk returns a tuple with the QueuedDateTime field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PendingOperationsPendingContentUpdate) GetQueuedDateTimeOk() (*time.Time, bool) { + if o == nil || IsNil(o.QueuedDateTime) { + return nil, false + } + return o.QueuedDateTime, true +} + +// HasQueuedDateTime returns a boolean if a field has been set. +func (o *PendingOperationsPendingContentUpdate) HasQueuedDateTime() bool { + if o != nil && !IsNil(o.QueuedDateTime) { + return true + } + + return false +} + +// SetQueuedDateTime gets a reference to the given time.Time and assigns it to the QueuedDateTime field. +func (o *PendingOperationsPendingContentUpdate) SetQueuedDateTime(v time.Time) { + o.QueuedDateTime = &v +} + +func (o PendingOperationsPendingContentUpdate) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o PendingOperationsPendingContentUpdate) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.QueuedDateTime) { + toSerialize["queuedDateTime"] = o.QueuedDateTime + } + return toSerialize, nil +} + +type NullablePendingOperationsPendingContentUpdate struct { + value *PendingOperationsPendingContentUpdate + isSet bool +} + +func (v NullablePendingOperationsPendingContentUpdate) Get() *PendingOperationsPendingContentUpdate { + return v.value +} + +func (v *NullablePendingOperationsPendingContentUpdate) Set(val *PendingOperationsPendingContentUpdate) { + v.value = val + v.isSet = true +} + +func (v NullablePendingOperationsPendingContentUpdate) IsSet() bool { + return v.isSet +} + +func (v *NullablePendingOperationsPendingContentUpdate) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePendingOperationsPendingContentUpdate(val *PendingOperationsPendingContentUpdate) *NullablePendingOperationsPendingContentUpdate { + return &NullablePendingOperationsPendingContentUpdate{value: val, isSet: true} +} + +func (v NullablePendingOperationsPendingContentUpdate) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePendingOperationsPendingContentUpdate) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/modules.txt b/vendor/modules.txt index c098b7652a..6ad68d0c38 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1364,7 +1364,7 @@ github.com/open-policy-agent/opa/v1/version # github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 ## explicit; go 1.24.6 github.com/opencloud-eu/icap-client -# github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260818063016-69f82a7dde55 +# github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260901070651-08a5330ce57d ## explicit; go 1.23 github.com/opencloud-eu/libre-graph-api-go # github.com/opencloud-eu/reva/v2 v2.49.0