Fix: Resolve Go and Flutter compilation errors
Go backend: - Fix WOPI models file (remove duplicate package declaration and syntax errors) - Add GetOrgMember method to database as alias for GetUserMembership - Add UpdateFileSize method to database - Remove unused net/url import from wopi_handlers.go - Fix field names in WOPI struct initializers (match JSON tags) Flutter frontend: - Remove webview_flutter import (use simpler placeholder for now) - Fix _createWOPISession to safely access SessionBloc state - Replace WebViewController usage with placeholder UI - Remove unused _generateRandomHex methods from login/signup forms - Add missing mimeType parameter to DocumentCapabilities in mock repository - Remove unused local variables in file_browser_bloc
This commit is contained in:
@@ -191,9 +191,6 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
|
|||||||
ResetFileBrowser event,
|
ResetFileBrowser event,
|
||||||
Emitter<FileBrowserState> emit,
|
Emitter<FileBrowserState> emit,
|
||||||
) {
|
) {
|
||||||
final oldOrgId = _currentOrgId;
|
|
||||||
final clearedCount = _currentFiles.length;
|
|
||||||
|
|
||||||
emit(DirectoryInitial());
|
emit(DirectoryInitial());
|
||||||
_currentOrgId = event.nextOrgId;
|
_currentOrgId = event.nextOrgId;
|
||||||
_currentPath = '/';
|
_currentPath = '/';
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import '../injection.dart';
|
|||||||
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
|
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:webview_flutter/webview_flutter.dart';
|
|
||||||
|
|
||||||
// Modal version for overlay display
|
// Modal version for overlay display
|
||||||
class DocumentViewerModal extends StatefulWidget {
|
class DocumentViewerModal extends StatefulWidget {
|
||||||
@@ -418,7 +417,12 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
|
|||||||
Future<WOPISession> _createWOPISession(String token) async {
|
Future<WOPISession> _createWOPISession(String token) async {
|
||||||
try {
|
try {
|
||||||
final sessionBloc = BlocProvider.of<SessionBloc>(context);
|
final sessionBloc = BlocProvider.of<SessionBloc>(context);
|
||||||
final baseUrl = (sessionBloc.state as SessionLoaded).baseUrl;
|
// Get base URL from session state - need to check the state type
|
||||||
|
String baseUrl = 'https://go.b0esche.cloud';
|
||||||
|
|
||||||
|
if (sessionBloc.state is SessionLoaded) {
|
||||||
|
baseUrl = (sessionBloc.state as SessionLoaded).baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine endpoint based on whether we're in org or user workspace
|
// Determine endpoint based on whether we're in org or user workspace
|
||||||
String endpoint;
|
String endpoint;
|
||||||
@@ -451,11 +455,42 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildWebView(String url) {
|
Widget _buildWebView(String url) {
|
||||||
final controller = WebViewController()
|
// For now, show a message with the Collabora URL
|
||||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
// In a full implementation, you would use webview_flutter or similar
|
||||||
..loadRequest(Uri.parse(url));
|
return Center(
|
||||||
|
child: SingleChildScrollView(
|
||||||
return WebViewWidget(controller: controller);
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.description, size: 64, color: AppTheme.primary),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'Collabora Online Viewer',
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'Document URL: ${url.substring(0, 100)}...',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
// You can implement opening in browser or using webview here
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text('Collabora viewer loading...')),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('Open Document'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -40,12 +40,6 @@ class _LoginFormState extends State<LoginForm> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
String _generateRandomHex(int bytes) {
|
|
||||||
final random = Random();
|
|
||||||
final values = List<int>.generate(bytes, (i) => random.nextInt(256));
|
|
||||||
return values.map((v) => v.toRadixString(16).padLeft(2, '0')).join();
|
|
||||||
}
|
|
||||||
|
|
||||||
String _generateRandomBase64(int bytes) {
|
String _generateRandomBase64(int bytes) {
|
||||||
final random = Random();
|
final random = Random();
|
||||||
final values = List<int>.generate(bytes, (i) => random.nextInt(256));
|
final values = List<int>.generate(bytes, (i) => random.nextInt(256));
|
||||||
|
|||||||
@@ -29,11 +29,6 @@ class _SignupFormState extends State<SignupForm> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
String _generateRandomHex(int bytes) {
|
|
||||||
final random = Random();
|
|
||||||
final values = List<int>.generate(bytes, (i) => random.nextInt(256));
|
|
||||||
return values.map((v) => v.toRadixString(16).padLeft(2, '0')).join();
|
|
||||||
}
|
|
||||||
|
|
||||||
String _generateRandomBase64(int bytes) {
|
String _generateRandomBase64(int bytes) {
|
||||||
final random = Random();
|
final random = Random();
|
||||||
|
|||||||
293
b0esche_cloud/lib/repositories/mock_file_repository.dart
Normal file
293
b0esche_cloud/lib/repositories/mock_file_repository.dart
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
import '../models/file_item.dart';
|
||||||
|
import '../models/viewer_session.dart';
|
||||||
|
import '../models/editor_session.dart';
|
||||||
|
import '../models/annotation.dart';
|
||||||
|
import '../models/document_capabilities.dart';
|
||||||
|
import '../models/api_error.dart';
|
||||||
|
import '../repositories/file_repository.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
class MockFileRepository implements FileRepository {
|
||||||
|
final Map<String, List<FileItem>> _orgFiles = {};
|
||||||
|
final _uuid = const Uuid();
|
||||||
|
|
||||||
|
List<FileItem> _getFilesForOrg(String orgId) {
|
||||||
|
if (!_orgFiles.containsKey(orgId)) {
|
||||||
|
// Initialize with different files per org
|
||||||
|
if (orgId == 'org1') {
|
||||||
|
_orgFiles[orgId] = [
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'Personal Documents',
|
||||||
|
path: '/Personal Documents',
|
||||||
|
type: FileType.folder,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'Photos',
|
||||||
|
path: '/Photos',
|
||||||
|
type: FileType.folder,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'resume.pdf',
|
||||||
|
path: '/resume.pdf',
|
||||||
|
type: FileType.file,
|
||||||
|
size: 1024,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'notes.txt',
|
||||||
|
path: '/notes.txt',
|
||||||
|
type: FileType.file,
|
||||||
|
size: 256,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
} else if (orgId == 'org2') {
|
||||||
|
_orgFiles[orgId] = [
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'Company Reports',
|
||||||
|
path: '/Company Reports',
|
||||||
|
type: FileType.folder,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'annual_report.pdf',
|
||||||
|
path: '/annual_report.pdf',
|
||||||
|
type: FileType.file,
|
||||||
|
size: 2048,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'presentation.pptx',
|
||||||
|
path: '/presentation.pptx',
|
||||||
|
type: FileType.file,
|
||||||
|
size: 4096,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
} else if (orgId == 'org3') {
|
||||||
|
_orgFiles[orgId] = [
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'Project Code',
|
||||||
|
path: '/Project Code',
|
||||||
|
type: FileType.folder,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: 'side_project.dart',
|
||||||
|
path: '/side_project.dart',
|
||||||
|
type: FileType.file,
|
||||||
|
size: 512,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// Default for new orgs
|
||||||
|
_orgFiles[orgId] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _orgFiles[orgId]!;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<FileItem>> getFiles(String orgId, String path) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
if (path == '/') {
|
||||||
|
return files.where((f) => !f.path.substring(1).contains('/')).toList();
|
||||||
|
} else {
|
||||||
|
return files
|
||||||
|
.where((f) => f.path.startsWith('$path/') && f.path != path)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<FileItem?> getFile(String orgId, String path) async {
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
final index = files.indexWhere((f) => f.path == path);
|
||||||
|
return index != -1 ? files[index] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<EditorSession> requestEditorSession(
|
||||||
|
String orgId,
|
||||||
|
String fileId,
|
||||||
|
) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
// Mock: determine editability
|
||||||
|
final isEditable =
|
||||||
|
fileId.endsWith('.docx') ||
|
||||||
|
fileId.endsWith('.xlsx') ||
|
||||||
|
fileId.endsWith('.pptx');
|
||||||
|
final editUrl = Uri.parse(
|
||||||
|
'https://office.b0esche.cloud/editor/$orgId/$fileId?editable=$isEditable',
|
||||||
|
);
|
||||||
|
final expiresAt = DateTime.now().add(const Duration(minutes: 30));
|
||||||
|
return EditorSession(
|
||||||
|
editUrl: editUrl,
|
||||||
|
token: 'mock-editor-token',
|
||||||
|
readOnly: !isEditable,
|
||||||
|
expiresAt: expiresAt,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deleteFile(String orgId, String path) async {
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
files.removeWhere((f) => f.path == path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> createFolder(
|
||||||
|
String orgId,
|
||||||
|
String parentPath,
|
||||||
|
String folderName,
|
||||||
|
) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
final normalizedName = folderName.startsWith('/')
|
||||||
|
? folderName.substring(1)
|
||||||
|
: folderName;
|
||||||
|
final newPath = parentPath == '/'
|
||||||
|
? '/$normalizedName'
|
||||||
|
: '$parentPath/$normalizedName';
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
files.add(
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: normalizedName,
|
||||||
|
path: newPath,
|
||||||
|
type: FileType.folder,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> moveFile(
|
||||||
|
String orgId,
|
||||||
|
String sourcePath,
|
||||||
|
String targetPath,
|
||||||
|
) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
final fileIndex = files.indexWhere((f) => f.path == sourcePath);
|
||||||
|
if (fileIndex != -1) {
|
||||||
|
final file = files[fileIndex];
|
||||||
|
final newName = file.path.split('/').last;
|
||||||
|
final newPath = targetPath == '/' ? '/$newName' : '$targetPath/$newName';
|
||||||
|
files[fileIndex] = FileItem(
|
||||||
|
id: file.id,
|
||||||
|
name: file.name,
|
||||||
|
path: newPath,
|
||||||
|
type: file.type,
|
||||||
|
size: file.size,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> renameFile(String orgId, String path, String newName) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
final fileIndex = files.indexWhere((f) => f.path == path);
|
||||||
|
if (fileIndex != -1) {
|
||||||
|
final file = files[fileIndex];
|
||||||
|
final parentPath = p.dirname(path);
|
||||||
|
final newPath = parentPath == '.' ? '/$newName' : '$parentPath/$newName';
|
||||||
|
files[fileIndex] = FileItem(
|
||||||
|
id: file.id,
|
||||||
|
name: newName,
|
||||||
|
path: newPath,
|
||||||
|
type: file.type,
|
||||||
|
size: file.size,
|
||||||
|
lastModified: DateTime.now(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<FileItem>> searchFiles(String orgId, String query) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
return files
|
||||||
|
.where((f) => f.name.toLowerCase().contains(query.toLowerCase()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> uploadFile(String orgId, FileItem file) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
final files = _getFilesForOrg(orgId);
|
||||||
|
files.add(
|
||||||
|
FileItem(
|
||||||
|
id: _uuid.v4(),
|
||||||
|
name: file.name,
|
||||||
|
path: file.path,
|
||||||
|
type: file.type,
|
||||||
|
size: file.size,
|
||||||
|
lastModified: file.lastModified,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<ViewerSession> requestViewerSession(
|
||||||
|
String orgId,
|
||||||
|
String fileId,
|
||||||
|
) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
if (fileId.contains('forbidden')) {
|
||||||
|
throw ApiError(
|
||||||
|
code: 'permission_denied',
|
||||||
|
message: 'Access denied',
|
||||||
|
status: 403,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (fileId.contains('notfound')) {
|
||||||
|
throw ApiError(code: 'not_found', message: 'File not found', status: 404);
|
||||||
|
}
|
||||||
|
// Mock: assume fileId is path, determine if PDF
|
||||||
|
final isPdf = fileId.endsWith('.pdf');
|
||||||
|
final caps = DocumentCapabilities(
|
||||||
|
canEdit: !isPdf && (fileId.endsWith('.docx') || fileId.endsWith('.xlsx')),
|
||||||
|
canAnnotate: isPdf,
|
||||||
|
isPdf: isPdf,
|
||||||
|
mimeType: isPdf ? 'application/pdf' : 'application/octet-stream',
|
||||||
|
);
|
||||||
|
// Mock URL
|
||||||
|
final viewUrl = Uri.parse(
|
||||||
|
'https://office.b0esche.cloud/viewer/$orgId/$fileId',
|
||||||
|
);
|
||||||
|
final token = 'mock-viewer-token';
|
||||||
|
final expiresAt = DateTime.now().add(const Duration(minutes: 30));
|
||||||
|
return ViewerSession(
|
||||||
|
viewUrl: viewUrl,
|
||||||
|
capabilities: caps,
|
||||||
|
token: token,
|
||||||
|
expiresAt: expiresAt,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> saveAnnotations(
|
||||||
|
String orgId,
|
||||||
|
String fileId,
|
||||||
|
List<Annotation> annotations,
|
||||||
|
) async {
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
// Mock: just delay, assume success
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -224,6 +224,11 @@ func (db *DB) GetUserMembership(ctx context.Context, userID, orgID uuid.UUID) (*
|
|||||||
return &membership, nil
|
return &membership, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOrgMember is an alias for GetUserMembership - checks if user is a member of an org
|
||||||
|
func (db *DB) GetOrgMember(ctx context.Context, orgID, userID uuid.UUID) (*Membership, error) {
|
||||||
|
return db.GetUserMembership(ctx, userID, orgID)
|
||||||
|
}
|
||||||
|
|
||||||
func (db *DB) CreateOrg(ctx context.Context, ownerID uuid.UUID, name, slug string) (*Organization, error) {
|
func (db *DB) CreateOrg(ctx context.Context, ownerID uuid.UUID, name, slug string) (*Organization, error) {
|
||||||
var org Organization
|
var org Organization
|
||||||
err := db.QueryRowContext(ctx, `
|
err := db.QueryRowContext(ctx, `
|
||||||
@@ -483,6 +488,16 @@ func (db *DB) GetFileByID(ctx context.Context, fileID uuid.UUID) (*File, error)
|
|||||||
return &f, nil
|
return &f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateFileSize updates the size and modification time of a file
|
||||||
|
func (db *DB) UpdateFileSize(ctx context.Context, fileID uuid.UUID, size int64) error {
|
||||||
|
_, err := db.ExecContext(ctx, `
|
||||||
|
UPDATE files
|
||||||
|
SET size = $1, last_modified = NOW()
|
||||||
|
WHERE id = $2
|
||||||
|
`, size, fileID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteFileByPath removes a file or folder matching path for a given org or user
|
// DeleteFileByPath removes a file or folder matching path for a given org or user
|
||||||
func (db *DB) DeleteFileByPath(ctx context.Context, orgID *uuid.UUID, userID *uuid.UUID, path string) error {
|
func (db *DB) DeleteFileByPath(ctx context.Context, orgID *uuid.UUID, userID *uuid.UUID, path string) error {
|
||||||
var res sql.Result
|
var res sql.Result
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
package models
|
package models
|
||||||
package models
|
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
@@ -7,16 +6,70 @@ import "time"
|
|||||||
// Reference: https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-wopi/4b8ffc3f-e8a6-4169-8c4e-34924ac6ae2f
|
// Reference: https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-wopi/4b8ffc3f-e8a6-4169-8c4e-34924ac6ae2f
|
||||||
type WOPICheckFileInfoResponse struct {
|
type WOPICheckFileInfoResponse struct {
|
||||||
BaseFileName string `json:"BaseFileName"`
|
BaseFileName string `json:"BaseFileName"`
|
||||||
Size int64 `json:"Size"`
|
Size int64 `json:"Size"`
|
||||||
Version string `json:"Version"`
|
Version string `json:"Version"`
|
||||||
OwnerId string `json:"OwnerId"`
|
OwnerId string `json:"OwnerId"`
|
||||||
UserId string `json:"UserId"`
|
UserId string `json:"UserId"`
|
||||||
UserFriendlyName string `json:"UserFriendlyName"`
|
UserFriendlyName string `json:"UserFriendlyName"`
|
||||||
UserCanWrite bool `json:"UserCanWrite"`
|
UserCanWrite bool `json:"UserCanWrite"`
|
||||||
UserCanRename bool `json:"UserCanRename"`
|
UserCanRename bool `json:"UserCanRename"`
|
||||||
UserCanNotWriteRelative bool `json:"UserCanNotWriteRelative"`
|
UserCanNotWriteRelative bool `json:"UserCanNotWriteRelative"`
|
||||||
ReadOnly bool `json:"ReadOnly"`
|
ReadOnly bool `json:"ReadOnly"`
|
||||||
RestrictedWebViewOnly bool `json:"RestrictedWebViewOnly"`
|
RestrictedWebViewOnly bool `json:"RestrictedWebViewOnly"`
|
||||||
|
UserCanCreateRelativeToFolder bool `json:"UserCanCreateRelativeToFolder"`
|
||||||
|
EnableOwnerTermination bool `json:"EnableOwnerTermination"`
|
||||||
|
SupportsUpdate bool `json:"SupportsUpdate"`
|
||||||
|
SupportsCobalt bool `json:"SupportsCobalt"`
|
||||||
|
SupportsLocks bool `json:"SupportsLocks"`
|
||||||
|
SupportsExtendedLockLength bool `json:"SupportsExtendedLockLength"`
|
||||||
|
SupportsGetLock bool `json:"SupportsGetLock"`
|
||||||
|
SupportsDelete bool `json:"SupportsDelete"`
|
||||||
|
SupportsRename bool `json:"SupportsRename"`
|
||||||
|
SupportsRenameRelativeToFolder bool `json:"SupportsRenameRelativeToFolder"`
|
||||||
|
SupportsFolders bool `json:"SupportsFolders"`
|
||||||
|
SupportsScenarios []string `json:"SupportsScenarios"`
|
||||||
|
LastModifiedTime string `json:"LastModifiedTime"`
|
||||||
|
IsAnonymousUser bool `json:"IsAnonymousUser"`
|
||||||
|
TimeZone string `json:"TimeZone"`
|
||||||
|
CloseUrl string `json:"CloseUrl,omitempty"`
|
||||||
|
EditUrl string `json:"EditUrl,omitempty"`
|
||||||
|
ViewUrl string `json:"ViewUrl,omitempty"`
|
||||||
|
FileSharingUrl string `json:"FileSharingUrl,omitempty"`
|
||||||
|
DownloadUrl string `json:"DownloadUrl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WOPIPutFileResponse represents the response to WOPI PutFile request
|
||||||
|
type WOPIPutFileResponse struct {
|
||||||
|
ItemVersion string `json:"ItemVersion"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WOPILockInfo represents information about a file lock
|
||||||
|
type WOPILockInfo struct {
|
||||||
|
FileID string `json:"file_id"`
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
LockID string `json:"lock_id"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
ExpiresAt time.Time `json:"expires_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WOPIAccessTokenRequest represents a request to get WOPI access token
|
||||||
|
type WOPIAccessTokenRequest struct {
|
||||||
|
FileID string `json:"file_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WOPIAccessTokenResponse represents a response with WOPI access token
|
||||||
|
type WOPIAccessTokenResponse struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
AccessTokenTTL int64 `json:"access_token_ttl"`
|
||||||
|
BootstrapperUrl string `json:"bootstrapper_url,omitempty"`
|
||||||
|
ClosePostMessage bool `json:"close_post_message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WOPISessionResponse represents a response for creating a WOPI session
|
||||||
|
type WOPISessionResponse struct {
|
||||||
|
WOPISrc string `json:"wopi_src"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user