ultisuite-backend/internal/driveroot/cloud_native.go
R3D347HR4Y 857b9afc43
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run
feat(drive): implement external URL resolution for mounted cloud files
- Added new functionality to resolve external URLs for files on Google Drive and Microsoft OneDrive mounts.
- Introduced `mount_cloud_service.go` to handle OAuth token extraction and URL resolution.
- Enhanced `mounts_service.go` to update mount configurations with OAuth tokens.
- Updated API routes to include a new endpoint for fetching external URLs.
- Implemented enrichment functions in `cloud_native.go` to mark files that should open in the provider's web editor.
- Added tests for cloud-native file enrichment in `cloud_native_test.go` to ensure correct behavior.
2026-06-13 13:44:43 +02:00

129 lines
3.5 KiB
Go

package driveroot
import (
"strings"
"github.com/ultisuite/ulti-backend/internal/nextcloud"
)
// NormalizeMountBackend maps stored backend_type to a provider family.
func NormalizeMountBackend(backendType string) string {
switch strings.TrimSpace(strings.ToLower(backendType)) {
case "googledrive", "google":
return "google"
case "onedrive", "microsoft":
return "microsoft"
default:
return strings.TrimSpace(strings.ToLower(backendType))
}
}
func isGoogleWorkspaceNativeMime(mimeType string) bool {
switch strings.TrimSpace(mimeType) {
case "application/vnd.google-apps.document",
"application/vnd.google-apps.spreadsheet",
"application/vnd.google-apps.presentation":
return true
default:
return false
}
}
func isMicrosoftOfficeMime(mimeType, name string) bool {
mime := strings.ToLower(strings.TrimSpace(mimeType))
switch mime {
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/msword",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.ms-powerpoint":
return true
}
ext := ""
if dot := strings.LastIndex(name, "."); dot >= 0 {
ext = strings.ToLower(name[dot+1:])
}
switch ext {
case "doc", "docx", "xls", "xlsx", "ppt", "pptx":
return true
default:
return false
}
}
func providerIDFromETag(etag string) string {
id := strings.Trim(strings.TrimSpace(etag), "\"")
if id == "" {
return ""
}
// Google Drive file ids are alphanumeric plus _ and -.
for _, r := range id {
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' || r == '-' {
continue
}
return ""
}
if len(id) < 10 {
return ""
}
return id
}
// GoogleWorkspaceWebURL builds a browser editor URL for native Google Workspace files.
func GoogleWorkspaceWebURL(mimeType, fileID string) string {
fileID = strings.TrimSpace(fileID)
if fileID == "" {
return ""
}
switch strings.TrimSpace(mimeType) {
case "application/vnd.google-apps.document":
return "https://docs.google.com/document/d/" + fileID + "/edit"
case "application/vnd.google-apps.spreadsheet":
return "https://docs.google.com/spreadsheets/d/" + fileID + "/edit"
case "application/vnd.google-apps.presentation":
return "https://docs.google.com/presentation/d/" + fileID + "/edit"
default:
return ""
}
}
func shouldOpenMountExternally(backend, mimeType, name string) bool {
backend = NormalizeMountBackend(backend)
if backend == "google" && isGoogleWorkspaceNativeMime(mimeType) {
return true
}
if backend == "microsoft" && isMicrosoftOfficeMime(mimeType, name) {
return true
}
return false
}
// EnrichMountCloudNative marks mount files that should open in the provider's web editor.
func EnrichMountCloudNative(file *nextcloud.FileInfo, mountBackend string) {
if file == nil || file.Type == "directory" {
return
}
backend := NormalizeMountBackend(mountBackend)
if backend == "" {
return
}
file.MountBackend = backend
if !shouldOpenMountExternally(backend, file.MimeType, file.Name) {
return
}
file.OpenExternally = true
if backend == "google" && isGoogleWorkspaceNativeMime(file.MimeType) {
if id := providerIDFromETag(file.ETag); id != "" {
file.ExternalURL = GoogleWorkspaceWebURL(file.MimeType, id)
}
}
}
func EnrichMountCloudNativeFiles(files []nextcloud.FileInfo, mountBackend string) []nextcloud.FileInfo {
for i := range files {
EnrichMountCloudNative(&files[i], mountBackend)
}
return files
}