From 757fc04e55fc5e19b3207ce3fc2af5f1e32c3f48 Mon Sep 17 00:00:00 2001 From: Roman Perekhod Date: Wed, 16 Apr 2025 10:34:53 +0200 Subject: [PATCH] Fix the expiration date response for links --- .gitignore | 2 +- .../unreleased/fix-public-link-expiration.md | 6 ++++ .../v0/api_driveitem_permissions_links.go | 18 +++------- .../api_driveitem_permissions_links_test.go | 34 +++++++++++++++++++ .../createDriveLinkShare.feature | 4 +-- .../createItemLinkShare.feature | 8 ++--- .../updateItemLinkShare.feature | 10 +++--- 7 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 changelog/unreleased/fix-public-link-expiration.md diff --git a/.gitignore b/.gitignore index 0a3cf4c3a25..548778e2f3c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ services/*/bin /ocis/dist/ services/*/assets ocis/ocis -ocis/cmd/ocis/__debug_bin +ocis/cmd/ocis/__debug_bin* ocis/cmd/ocis/config/ # docs diff --git a/changelog/unreleased/fix-public-link-expiration.md b/changelog/unreleased/fix-public-link-expiration.md new file mode 100644 index 00000000000..62959cbf408 --- /dev/null +++ b/changelog/unreleased/fix-public-link-expiration.md @@ -0,0 +1,6 @@ +Bugfix: Fix the expiration date response for links + +We fixed the inconsistency in the expiration date response for links + +https://github.com/owncloud/ocis/pull/11239 +https://github.com/owncloud/ocis/issues/11232 diff --git a/services/graph/pkg/service/v0/api_driveitem_permissions_links.go b/services/graph/pkg/service/v0/api_driveitem_permissions_links.go index 0e0de70c11a..8b4f5c4c390 100644 --- a/services/graph/pkg/service/v0/api_driveitem_permissions_links.go +++ b/services/graph/pkg/service/v0/api_driveitem_permissions_links.go @@ -62,7 +62,7 @@ func (s DriveItemPermissionsService) CreateLink(ctx context.Context, driveItemID } expirationDate, isSet := createLink.GetExpirationDateTimeOk() if isSet { - expireTime := parseAndFillUpTime(expirationDate) + expireTime := timePointerToTS(expirationDate) if expireTime == nil { s.logger.Debug().Interface("createLink", createLink).Send() return libregraph.Permission{}, errorcode.New(errorcode.InvalidRequest, "invalid expiration date") @@ -298,7 +298,7 @@ func (s DriveItemPermissionsService) updatePublicLinkPermission(ctx context.Cont expirationDate := newPermission.GetExpirationDateTime() update := &link.UpdatePublicShareRequest_Update{ Type: link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION, - Grant: &link.Grant{Expiration: parseAndFillUpTime(&expirationDate)}, + Grant: &link.Grant{Expiration: timePointerToTS(&expirationDate)}, } perm, err = s.updatePublicLink(ctx, permissionID, update) if err != nil { @@ -410,19 +410,9 @@ func (s DriveItemPermissionsService) updatePublicLink(ctx context.Context, permi return permission, nil } -func parseAndFillUpTime(t *time.Time) *types.Timestamp { +func timePointerToTS(t *time.Time) *types.Timestamp { if t == nil || t.IsZero() { return nil } - - // the link needs to be valid for the whole day - tLink := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) - tLink = tLink.Add(23*time.Hour + 59*time.Minute + 59*time.Second) - - final := tLink.UnixNano() - - return &types.Timestamp{ - Seconds: uint64(final / 1000000000), - Nanos: uint32(final % 1000000000), - } + return utils.TimeToTS(*t) } diff --git a/services/graph/pkg/service/v0/api_driveitem_permissions_links_test.go b/services/graph/pkg/service/v0/api_driveitem_permissions_links_test.go index b06af56d247..1e398e74cb4 100644 --- a/services/graph/pkg/service/v0/api_driveitem_permissions_links_test.go +++ b/services/graph/pkg/service/v0/api_driveitem_permissions_links_test.go @@ -206,7 +206,41 @@ var _ = Describe("createLinkTests", func() { Expect(libreGraphActions[1]).To(Equal("libre.graph/driveItem/upload/create")) Expect(libreGraphActions[2]).To(Equal("libre.graph/driveItem/path/update")) }) + + It("does not alter the provided expiration timestamp", func() { + // prepare test timestamp + providedExp := time.Date(2025, 5, 12, 7, 37, 0, 0, time.UTC) + driveItemCreateLink.ExpirationDateTime = libregraph.PtrTime(providedExp) + + // prepare expected permissions for response + permissions, err := linktype.CS3ResourcePermissionsFromSharingLink(driveItemCreateLink, provider.ResourceType_RESOURCE_TYPE_CONTAINER) + Expect(err).ToNot(HaveOccurred()) + + // mock Stat + gatewayClient.On("Stat", mock.Anything, mock.Anything).Return(statResponse, nil) + + // assert that the CreatePublicShare request contains EXACT expiration time (no end-of-day adjustment) + gatewayClient.On("CreatePublicShare", mock.Anything, mock.MatchedBy(func(req *link.CreatePublicShareRequest) bool { + exp := utils.TSToTime(req.GetGrant().GetExpiration()) + return exp.Equal(providedExp) + })).Return(&link.CreatePublicShareResponse{ + Status: status.NewOK(ctx), + Share: &link.PublicShare{ + Id: &link.PublicShareId{OpaqueId: "expTest"}, + Expiration: utils.TimeToTS(providedExp), + DisplayName: ViewerLinkString, + Token: "token", + Permissions: &link.PublicSharePermissions{Permissions: permissions}, + }, + }, nil) + + perm, err := svc.CreateLink(context.Background(), driveItemId, driveItemCreateLink) + Expect(err).ToNot(HaveOccurred()) + Expect(perm.GetId()).To(Equal("expTest")) + Expect(perm.GetExpirationDateTime().Equal(providedExp)).To(BeTrue()) + }) }) + Describe("SetLinPassword", func() { var ( updatePublicShareMockResponse link.UpdatePublicShareResponse diff --git a/tests/acceptance/features/apiSharingNgDriveLinkShare/createDriveLinkShare.feature b/tests/acceptance/features/apiSharingNgDriveLinkShare/createDriveLinkShare.feature index 1d0edf08c85..2a2b177260d 100644 --- a/tests/acceptance/features/apiSharingNgDriveLinkShare/createDriveLinkShare.feature +++ b/tests/acceptance/features/apiSharingNgDriveLinkShare/createDriveLinkShare.feature @@ -54,7 +54,7 @@ Feature: Link sharing of project spaces "properties": { "hasPassword": {"const": true}, "id": {"pattern": "^[a-zA-Z]{15}$"}, - "expirationDateTime": {"const": "2200-07-15T23:59:59Z"}, + "expirationDateTime": {"const": "2200-07-15T14:00:00Z"}, "link": { "type": "object", "required": ["@libre.graph.displayName","@libre.graph.quickLink","preventsDownload","type","webUrl"], @@ -152,7 +152,7 @@ Feature: Link sharing of project spaces "properties": { "hasPassword": {"const": true}, "id": {"pattern": "^[a-zA-Z]{15}$"}, - "expirationDateTime": {"const": "2200-07-15T23:59:59Z"}, + "expirationDateTime": {"const": "2200-07-15T14:00:00Z"}, "link": { "type": "object", "required": ["@libre.graph.displayName","@libre.graph.quickLink","preventsDownload","type","webUrl"], diff --git a/tests/acceptance/features/apiSharingNgItemLinkShare/createItemLinkShare.feature b/tests/acceptance/features/apiSharingNgItemLinkShare/createItemLinkShare.feature index 96e3e8addfb..fc7c5607754 100644 --- a/tests/acceptance/features/apiSharingNgItemLinkShare/createItemLinkShare.feature +++ b/tests/acceptance/features/apiSharingNgItemLinkShare/createItemLinkShare.feature @@ -55,7 +55,7 @@ Feature: Link share for resources "createdDateTime": {"format": "date-time"}, "hasPassword": {"const": true}, "id": {"pattern": "^[a-zA-Z]{15}$"}, - "expirationDateTime": {"const": "2200-07-15T23:59:59Z"}, + "expirationDateTime": {"const": "2200-07-15T14:00:00Z"}, "link": { "type": "object", "required": ["@libre.graph.displayName","@libre.graph.quickLink","preventsDownload","type","webUrl"], @@ -157,7 +157,7 @@ Feature: Link share for resources "createdDateTime": {"format": "date-time"}, "hasPassword": {"const": true}, "id": {"pattern": "^[a-zA-Z]{15}$"}, - "expirationDateTime": {"const": "2200-07-15T23:59:59Z"}, + "expirationDateTime": {"const": "2200-07-15T14:00:00Z"}, "link": { "type": "object", "required": ["@libre.graph.displayName","@libre.graph.quickLink","preventsDownload","type","webUrl"], @@ -258,7 +258,7 @@ Feature: Link share for resources "properties": { "hasPassword": {"const": true}, "id": {"pattern": "^[a-zA-Z]{15}$"}, - "expirationDateTime": {"const": "2200-07-15T23:59:59Z"}, + "expirationDateTime": {"const": "2200-07-15T14:00:00Z"}, "link": { "type": "object", "required": ["@libre.graph.displayName","@libre.graph.quickLink","preventsDownload","type","webUrl"], @@ -360,7 +360,7 @@ Feature: Link share for resources "properties": { "hasPassword": {"const": true}, "id": {"pattern": "^[a-zA-Z]{15}$"}, - "expirationDateTime": {"const": "2200-07-15T23:59:59Z"}, + "expirationDateTime": {"const": "2200-07-15T14:00:00Z"}, "link": { "type": "object", "required": ["@libre.graph.displayName","@libre.graph.quickLink","preventsDownload","type","webUrl"], diff --git a/tests/acceptance/features/apiSharingNgLinkShareManagement/updateItemLinkShare.feature b/tests/acceptance/features/apiSharingNgLinkShareManagement/updateItemLinkShare.feature index 23c9f6592d0..43e65670dd0 100644 --- a/tests/acceptance/features/apiSharingNgLinkShareManagement/updateItemLinkShare.feature +++ b/tests/acceptance/features/apiSharingNgLinkShareManagement/updateItemLinkShare.feature @@ -174,7 +174,7 @@ Feature: Update a link share for a resource "pattern": "^[a-zA-Z]{15}$" }, "expirationDateTime": { - "const": "2201-07-15T23:59:59Z" + "const": "2201-07-15T14:00:00Z" }, "link": { "type": "object", @@ -356,7 +356,7 @@ Feature: Update a link share for a resource "pattern": "^[a-zA-Z]{15}$" }, "expirationDateTime": { - "const": "2201-07-15T23:59:59Z" + "const": "2201-07-15T14:00:00Z" }, "link": { "type": "object", @@ -442,7 +442,7 @@ Feature: Update a link share for a resource "pattern": "^[a-zA-Z]{15}$" }, "expirationDateTime": { - "const": "2201-07-15T23:59:59Z" + "const": "2201-07-15T14:00:00Z" }, "link": { "type": "object", @@ -671,7 +671,7 @@ Feature: Update a link share for a resource "pattern": "^[a-zA-Z]{15}$" }, "expirationDateTime": { - "const": "2201-07-15T23:59:59Z" + "const": "2201-07-15T14:00:00Z" }, "link": { "type": "object", @@ -748,7 +748,7 @@ Feature: Update a link share for a resource "pattern": "^[a-zA-Z]{15}$" }, "expirationDateTime": { - "const": "2201-07-15T23:59:59Z" + "const": "2201-07-15T14:00:00Z" }, "link": { "type": "object",