mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-10-30 10:08:39 -04:00
feat(collaboration): close the CheckFileInfo gaps for the office apps
This commit is contained in:
1 parent
4086fad778
commit
09dba5bcaa
4 files changed
+217
-3
No files matched your search
@@ -1272,6 +1272,13 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
logger.Error().Err(err).Msg("CheckFileInfo: error getting scopes from the context")
|
||||
}
|
||||
}
|
||||
// the space root id must not reach a public share, like the parent folder link above
|
||||
breadcrumbBrandURL := ""
|
||||
if spaceRoot := statRes.GetInfo().GetSpace().GetRoot(); !isPublicShare && spaceRoot != nil {
|
||||
brandURL := *ocURL
|
||||
brandURL.Path = path.Join(ocURL.Path, "f", storagespace.FormatResourceID(spaceRoot))
|
||||
breadcrumbBrandURL = brandURL.String()
|
||||
}
|
||||
lastModifiedTime := time.Now().UTC().Format(lastModifiedTimeFormat)
|
||||
if mtime := statRes.GetInfo().GetMtime(); mtime != nil {
|
||||
lastModifiedTime = utils.TSToTime(mtime).UTC().Format(lastModifiedTimeFormat)
|
||||
@@ -1287,7 +1294,10 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
// to get the folder we actually need to do a GetPath() request
|
||||
fileinfo.KeyBreadcrumbFolderName: breadcrumbFolderName,
|
||||
fileinfo.KeyBreadcrumbFolderURL: parentFolderURL.String(),
|
||||
fileinfo.KeyBreadcrumbBrandName: statRes.GetInfo().GetSpace().GetName(),
|
||||
fileinfo.KeyBreadcrumbBrandURL: breadcrumbBrandURL,
|
||||
|
||||
fileinfo.KeyCloseURL: parentFolderURL.String(),
|
||||
fileinfo.KeyHostViewURL: createHostUrl("view", ocURL, f.cfg.App.Name, statRes.GetInfo()),
|
||||
fileinfo.KeyHostEditURL: createHostUrl("write", ocURL, f.cfg.App.Name, statRes.GetInfo()),
|
||||
fileinfo.KeyFileSharingURL: createShareUrl(privateLinkURL),
|
||||
@@ -1325,6 +1335,13 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
infoMap[fileinfo.KeySize] = size
|
||||
}
|
||||
|
||||
infoMap[fileinfo.KeyReadOnly] = wopiContext.ViewMode != appproviderv1beta1.ViewMode_VIEW_MODE_READ_WRITE
|
||||
|
||||
// only the collabora integration in web handles UI_Edit, the other office apps would post into the void
|
||||
if strings.ToLower(f.cfg.App.Product) == "collabora" {
|
||||
infoMap[fileinfo.KeyEditModePostMessage] = true
|
||||
}
|
||||
|
||||
switch wopiContext.ViewMode {
|
||||
case appproviderv1beta1.ViewMode_VIEW_MODE_READ_WRITE:
|
||||
infoMap[fileinfo.KeyUserCanWrite] = true
|
||||
@@ -1337,9 +1354,12 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
|
||||
infoMap[fileinfo.KeyDisableExport] = true // only for collabora
|
||||
infoMap[fileinfo.KeyDisableCopy] = true // only for collabora
|
||||
infoMap[fileinfo.KeyDisablePrint] = true
|
||||
// a viewer role opens the document view only as well, the watermark is for secure view
|
||||
if !isPublicShare && wopiContext.ViewOnlyToken != "" {
|
||||
infoMap[fileinfo.KeyWatermarkText] = f.watermarkText(user) // only for collabora
|
||||
// a viewer role opens the document view only as well, lock and watermark are for secure view
|
||||
if wopiContext.ViewOnlyToken != "" {
|
||||
infoMap[fileinfo.KeyIsUserLocked] = true // only for collabora
|
||||
if !isPublicShare {
|
||||
infoMap[fileinfo.KeyWatermarkText] = f.watermarkText(user) // only for collabora
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1762,6 +1762,7 @@ var _ = Describe("FileConnector", func() {
|
||||
FileVersionURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=versions",
|
||||
HostEditURL: "https://cloud.opencloud.test/external-test/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=write",
|
||||
HostViewURL: "https://cloud.opencloud.test/external-test/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=view",
|
||||
CloseURL: "https://cloud.opencloud.test/f/storageid$spaceid%21parentopaqueid",
|
||||
}
|
||||
|
||||
response, err := fc.CheckFileInfo(ctx)
|
||||
@@ -1838,6 +1839,18 @@ var _ = Describe("FileConnector", func() {
|
||||
EnableInsertRemoteFile: true,
|
||||
EnableRemoteLinkPicker: true,
|
||||
IsAnonymousUser: true,
|
||||
Version: "v162738490",
|
||||
LastModifiedTime: "1970-07-08T08:30:49.0000000Z",
|
||||
ReadOnly: true,
|
||||
SupportsUpdate: true,
|
||||
BreadcrumbFolderName: "/path/to",
|
||||
BreadcrumbFolderURL: "https://cloud.opencloud.test",
|
||||
CloseURL: "https://cloud.opencloud.test",
|
||||
FileSharingURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=sharing",
|
||||
FileVersionURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=versions",
|
||||
HostEditURL: "https://cloud.opencloud.test/external-collabora/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=write",
|
||||
HostViewURL: "https://cloud.opencloud.test/external-collabora/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=view",
|
||||
EditModePostMessage: true,
|
||||
}
|
||||
|
||||
response, err := fc.CheckFileInfo(ctx)
|
||||
@@ -1944,6 +1957,8 @@ var _ = Describe("FileConnector", func() {
|
||||
FileVersionURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=versions",
|
||||
HostEditURL: "https://cloud.opencloud.test/external-onlyoffice/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=write",
|
||||
PostMessageOrigin: "https://cloud.opencloud.test",
|
||||
CloseURL: "https://cloud.opencloud.test/s/ABC123",
|
||||
ReadOnly: true,
|
||||
}
|
||||
|
||||
response, err := fc.CheckFileInfo(ctx)
|
||||
@@ -2035,6 +2050,19 @@ var _ = Describe("FileConnector", func() {
|
||||
EnableInsertRemoteFile: true,
|
||||
EnableRemoteLinkPicker: true,
|
||||
IsAdminUser: true,
|
||||
Version: "v162738490",
|
||||
LastModifiedTime: "1970-07-08T08:30:49.0000000Z",
|
||||
ReadOnly: true,
|
||||
SupportsUpdate: true,
|
||||
BreadcrumbFolderName: "/path/to",
|
||||
BreadcrumbFolderURL: "https://cloud.opencloud.test/f/storageid$spaceid%21parentopaqueid",
|
||||
CloseURL: "https://cloud.opencloud.test/f/storageid$spaceid%21parentopaqueid",
|
||||
FileSharingURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=sharing",
|
||||
FileVersionURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=versions",
|
||||
HostEditURL: "https://cloud.opencloud.test/external-collabora/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=write",
|
||||
HostViewURL: "https://cloud.opencloud.test/external-collabora/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=view",
|
||||
EditModePostMessage: true,
|
||||
IsUserLocked: true,
|
||||
UserExtraInfo: &fileinfo.UserExtraInfo{
|
||||
Mail: "shaft@example.com",
|
||||
},
|
||||
@@ -2128,6 +2156,18 @@ var _ = Describe("FileConnector", func() {
|
||||
EnableInsertRemoteFile: true,
|
||||
EnableRemoteLinkPicker: true,
|
||||
IsAdminUser: true,
|
||||
Version: "v162738490",
|
||||
LastModifiedTime: "1970-07-08T08:30:49.0000000Z",
|
||||
ReadOnly: true,
|
||||
SupportsUpdate: true,
|
||||
BreadcrumbFolderName: "/path/to",
|
||||
BreadcrumbFolderURL: "https://cloud.opencloud.test/f/storageid$spaceid%21parentopaqueid",
|
||||
CloseURL: "https://cloud.opencloud.test/f/storageid$spaceid%21parentopaqueid",
|
||||
FileSharingURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=sharing",
|
||||
FileVersionURL: "https://cloud.opencloud.test/f/storageid$spaceid%21opaqueid?details=versions",
|
||||
HostEditURL: "https://cloud.opencloud.test/external-collabora/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=write",
|
||||
HostViewURL: "https://cloud.opencloud.test/external-collabora/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=view",
|
||||
EditModePostMessage: true,
|
||||
UserExtraInfo: &fileinfo.UserExtraInfo{
|
||||
Mail: "shaft@example.com",
|
||||
},
|
||||
@@ -2218,6 +2258,7 @@ var _ = Describe("FileConnector", func() {
|
||||
HostEditURL: "https://cloud.opencloud.test/external-onlyoffice/path/to/test.txt?fileId=storageid%24spaceid%21opaqueid&view_mode=write",
|
||||
PostMessageOrigin: "https://cloud.opencloud.test",
|
||||
EnableInsertRemoteImage: true,
|
||||
CloseURL: "https://cloud.opencloud.test/f/storageid$spaceid%21parentopaqueid",
|
||||
}
|
||||
|
||||
// change wopi app provider
|
||||
@@ -2320,6 +2361,87 @@ var _ = Describe("FileConnector", func() {
|
||||
Expect(lastModified).To(BeTemporally("~", time.Now().UTC(), time.Minute))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Breadcrumb brand", func() {
|
||||
statFileInSpace := func(ctx context.Context) {
|
||||
gatewayClient.On("Stat", mock.Anything, mock.Anything).Times(1).Return(&providerv1beta1.StatResponse{
|
||||
Status: status.NewOK(ctx),
|
||||
Info: &providerv1beta1.ResourceInfo{
|
||||
Owner: &userv1beta1.UserId{
|
||||
Idp: "customIdp",
|
||||
OpaqueId: "aabbcc",
|
||||
Type: userv1beta1.UserType_USER_TYPE_PRIMARY,
|
||||
},
|
||||
Size: uint64(998877),
|
||||
Path: "/path/to/test.txt",
|
||||
Id: &providerv1beta1.ResourceId{
|
||||
StorageId: "storageid",
|
||||
OpaqueId: "opaqueid",
|
||||
SpaceId: "spaceid",
|
||||
},
|
||||
ParentId: &providerv1beta1.ResourceId{
|
||||
StorageId: "storageid",
|
||||
OpaqueId: "parentopaqueid",
|
||||
SpaceId: "spaceid",
|
||||
},
|
||||
Space: &providerv1beta1.StorageSpace{
|
||||
Name: "Project X",
|
||||
Root: &providerv1beta1.ResourceId{
|
||||
StorageId: "storageid",
|
||||
OpaqueId: "spaceid",
|
||||
SpaceId: "spaceid",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
cfg.App.Name = "Collabora"
|
||||
cfg.App.Product = "Collabora"
|
||||
})
|
||||
|
||||
It("names and links the space for an authenticated user", func() {
|
||||
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
|
||||
ctx = ctxpkg.ContextSetUser(ctx, &userv1beta1.User{
|
||||
Id: &userv1beta1.UserId{
|
||||
Idp: "example.com",
|
||||
OpaqueId: "aabbcc",
|
||||
Type: userv1beta1.UserType_USER_TYPE_PRIMARY,
|
||||
},
|
||||
DisplayName: "Pet Shaft",
|
||||
})
|
||||
gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Return(
|
||||
&permissions.CheckPermissionResponse{Status: status.NewOK(ctx)},
|
||||
nil,
|
||||
)
|
||||
statFileInSpace(ctx)
|
||||
|
||||
response, err := fc.CheckFileInfo(ctx)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
body := response.Body.(*fileinfo.Collabora)
|
||||
Expect(body.BreadcrumbBrandName).To(Equal("Project X"))
|
||||
Expect(body.BreadcrumbBrandURL).To(Equal("https://cloud.opencloud.test/f/storageid$spaceid%21spaceid"))
|
||||
})
|
||||
|
||||
It("names the space but keeps its link from a public share", func() {
|
||||
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
|
||||
ctx = ctxpkg.ContextSetUser(ctx, &userv1beta1.User{
|
||||
Opaque: &typesv1beta1.Opaque{
|
||||
Map: map[string]*typesv1beta1.OpaqueEntry{
|
||||
"public-share-role": {Decoder: "plain", Value: []byte("viewer")},
|
||||
},
|
||||
},
|
||||
})
|
||||
statFileInSpace(ctx)
|
||||
|
||||
response, err := fc.CheckFileInfo(ctx)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
body := response.Body.(*fileinfo.Collabora)
|
||||
Expect(body.BreadcrumbBrandName).To(Equal("Project X"))
|
||||
Expect(body.BreadcrumbBrandURL).To(BeEmpty())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("GetAvatar", func() {
|
||||
|
||||
@@ -27,6 +27,14 @@ type Collabora struct {
|
||||
PostMessageOrigin string `json:"PostMessageOrigin,omitempty"`
|
||||
// copied from MS WOPI
|
||||
Size int64 `json:"Size"`
|
||||
// The file version, it changes with every change of the file and never repeats.
|
||||
Version string `json:"Version,omitempty"`
|
||||
// The last modification of the file as UTC time in ISO 8601 round-trip format.
|
||||
LastModifiedTime string `json:"LastModifiedTime,omitempty"`
|
||||
// If set to true, the file cannot be changed by this user.
|
||||
ReadOnly bool `json:"ReadOnly"`
|
||||
// If set to true, PutFile and PutRelativeFile are available.
|
||||
SupportsUpdate bool `json:"SupportsUpdate"`
|
||||
// The ID of file (like the wopi/files/ID) can be a non-existing file. In that case, the file will be created from a template when the template (eg. an OTT file) is specified as TemplateSource in the CheckFileInfo response. The TemplateSource is supposed to be an URL like https://somewhere/accessible/file.ott that is accessible by the Online. For the actual saving of the content, normal PutFile mechanism will be used.
|
||||
TemplateSource string `json:"TemplateSource,omitempty"`
|
||||
// copied from MS WOPI
|
||||
@@ -38,6 +46,34 @@ type Collabora struct {
|
||||
// copied from MS WOPI
|
||||
UserFriendlyName string `json:"UserFriendlyName,omitempty"`
|
||||
|
||||
//
|
||||
// URL properties
|
||||
//
|
||||
|
||||
// The page to navigate to when the editor closes or fails unrecoverably.
|
||||
CloseURL string `json:"CloseUrl,omitempty"`
|
||||
// The page that lets the user share the file.
|
||||
FileSharingURL string `json:"FileSharingUrl,omitempty"`
|
||||
// The page that shows the version history of the file.
|
||||
FileVersionURL string `json:"FileVersionUrl,omitempty"`
|
||||
// The host page that opens the file in edit mode.
|
||||
HostEditURL string `json:"HostEditUrl,omitempty"`
|
||||
// The host page that opens the file in view mode.
|
||||
HostViewURL string `json:"HostViewUrl,omitempty"`
|
||||
|
||||
//
|
||||
// Breadcrumb properties
|
||||
//
|
||||
|
||||
// The name shown as the brand part of the breadcrumb, the space name.
|
||||
BreadcrumbBrandName string `json:"BreadcrumbBrandName,omitempty"`
|
||||
// The page to navigate to from the breadcrumb brand.
|
||||
BreadcrumbBrandURL string `json:"BreadcrumbBrandUrl,omitempty"`
|
||||
// The name of the folder that contains the file.
|
||||
BreadcrumbFolderName string `json:"BreadcrumbFolderName,omitempty"`
|
||||
// The page to navigate to from the breadcrumb folder.
|
||||
BreadcrumbFolderURL string `json:"BreadcrumbFolderUrl,omitempty"`
|
||||
|
||||
//
|
||||
// Extended response properties
|
||||
//
|
||||
@@ -64,6 +100,8 @@ type Collabora struct {
|
||||
DisableInactiveMessages bool `json:"DisableInactiveMessages,omitempty"`
|
||||
// Indicate that the integration wants to handle the downloading of pdf for printing or svg for slideshows or exported document, because it cannot rely on browser’s support for downloading.
|
||||
DownloadAsPostMessage bool `json:"DownloadAsPostMessage,omitempty"`
|
||||
// If set to true, a UI_Edit postMessage is sent when the user switches to edit mode.
|
||||
EditModePostMessage bool `json:"EditModePostMessage,omitempty"`
|
||||
// Similar to download as, doctype extensions can be provided for save-as. In this case the new file is loaded in the integration instead of downloaded.
|
||||
SaveAsPostmessage bool `json:"SaveAsPostmessage,omitempty"`
|
||||
// If set to true, it allows the document owner (the one with OwnerId =UserId) to send a closedocument message (see protocol.txt)
|
||||
@@ -72,6 +110,8 @@ type Collabora struct {
|
||||
IsAdminUser bool `json:"IsAdminUser"`
|
||||
// If set to true, some functionality of Collabora which is supposed to be shown to authenticated users only is hidden
|
||||
IsAnonymousUser bool `json:"IsAnonymousUser,omitempty"`
|
||||
// If set to true, the feature lock configured in Collabora restricts the commands available to this user.
|
||||
IsUserLocked bool `json:"IsUserLocked,omitempty"`
|
||||
|
||||
// JSON object that contains additional info about the user, namely the avatar image.
|
||||
// Shared among all views in collaborative editing sessions.
|
||||
@@ -111,6 +151,12 @@ func (cinfo *Collabora) SetProperties(props map[string]any) {
|
||||
cinfo.PostMessageOrigin = value.(string)
|
||||
case KeySize:
|
||||
cinfo.Size = value.(int64)
|
||||
case KeyVersion:
|
||||
cinfo.Version = value.(string)
|
||||
case KeyLastModifiedTime:
|
||||
cinfo.LastModifiedTime = value.(string)
|
||||
case KeyReadOnly:
|
||||
cinfo.ReadOnly = value.(bool)
|
||||
case KeyTemplateSource:
|
||||
cinfo.TemplateSource = value.(string)
|
||||
case KeyUserCanWrite:
|
||||
@@ -122,6 +168,17 @@ func (cinfo *Collabora) SetProperties(props map[string]any) {
|
||||
case KeyUserFriendlyName:
|
||||
cinfo.UserFriendlyName = value.(string)
|
||||
|
||||
case KeyCloseURL:
|
||||
cinfo.CloseURL = value.(string)
|
||||
case KeyFileSharingURL:
|
||||
cinfo.FileSharingURL = value.(string)
|
||||
case KeyFileVersionURL:
|
||||
cinfo.FileVersionURL = value.(string)
|
||||
case KeyHostEditURL:
|
||||
cinfo.HostEditURL = value.(string)
|
||||
case KeyHostViewURL:
|
||||
cinfo.HostViewURL = value.(string)
|
||||
|
||||
case KeyEnableInsertRemoteImage:
|
||||
cinfo.EnableInsertRemoteImage = value.(bool)
|
||||
case KeyEnableInsertRemoteFile:
|
||||
@@ -144,6 +201,8 @@ func (cinfo *Collabora) SetProperties(props map[string]any) {
|
||||
cinfo.DisableInactiveMessages = value.(bool)
|
||||
case KeyDownloadAsPostMessage:
|
||||
cinfo.DownloadAsPostMessage = value.(bool)
|
||||
case KeyEditModePostMessage:
|
||||
cinfo.EditModePostMessage = value.(bool)
|
||||
case KeySaveAsPostmessage:
|
||||
cinfo.SaveAsPostmessage = value.(bool)
|
||||
case KeyEnableOwnerTermination:
|
||||
@@ -157,6 +216,8 @@ func (cinfo *Collabora) SetProperties(props map[string]any) {
|
||||
cinfo.IsAdminUser = value.(bool)
|
||||
case KeyIsAnonymousUser:
|
||||
cinfo.IsAnonymousUser = value.(bool)
|
||||
case KeyIsUserLocked:
|
||||
cinfo.IsUserLocked = value.(bool)
|
||||
|
||||
case KeyEnableShare:
|
||||
cinfo.EnableShare = value.(bool)
|
||||
@@ -170,6 +231,16 @@ func (cinfo *Collabora) SetProperties(props map[string]any) {
|
||||
cinfo.UserCanRename = value.(bool)
|
||||
case KeyBreadcrumbDocName:
|
||||
cinfo.BreadcrumbDocName = value.(string)
|
||||
case KeySupportsUpdate:
|
||||
cinfo.SupportsUpdate = value.(bool)
|
||||
case KeyBreadcrumbBrandName:
|
||||
cinfo.BreadcrumbBrandName = value.(string)
|
||||
case KeyBreadcrumbBrandURL:
|
||||
cinfo.BreadcrumbBrandURL = value.(string)
|
||||
case KeyBreadcrumbFolderName:
|
||||
cinfo.BreadcrumbFolderName = value.(string)
|
||||
case KeyBreadcrumbFolderURL:
|
||||
cinfo.BreadcrumbFolderURL = value.(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ const (
|
||||
KeyIsAnonymousUser = "IsAnonymousUser"
|
||||
KeyIsEduUser = "IsEduUser"
|
||||
KeyIsAdminUser = "IsAdminUser"
|
||||
KeyIsUserLocked = "IsUserLocked"
|
||||
KeyLicenseCheckForEditIsEnabled = "LicenseCheckForEditIsEnabled"
|
||||
KeyUserFriendlyName = "UserFriendlyName"
|
||||
KeyUserInfo = "UserInfo"
|
||||
|
||||
Reference in new issue
Block a user