This commit is contained in:
Leon Bösche
2026-01-09 17:01:41 +01:00
parent e9df8f7d9f
commit ebb97f4f39
5 changed files with 82 additions and 31 deletions

View File

@@ -16,7 +16,9 @@ void configureDependencies(SessionBloc sessionBloc) {
// Register repositories (HTTP-backed) // Register repositories (HTTP-backed)
final apiClient = ApiClient(sessionBloc); final apiClient = ApiClient(sessionBloc);
getIt.registerSingleton<AuthRepository>(HttpAuthRepository(apiClient)); getIt.registerSingleton<AuthRepository>(HttpAuthRepository(apiClient));
getIt.registerSingleton<FileRepository>(HttpFileRepository(FileService(apiClient))); getIt.registerSingleton<FileRepository>(
HttpFileRepository(FileService(apiClient)),
);
// Register services // Register services
getIt.registerSingleton<AuthService>(AuthService(getIt<AuthRepository>())); getIt.registerSingleton<AuthService>(AuthService(getIt<AuthRepository>()));

View File

@@ -8,18 +8,21 @@ class HttpAuthRepository implements AuthRepository {
@override @override
Future<User> login(String email, String password) async { Future<User> login(String email, String password) async {
final res = await _apiClient.post('/auth/password-login', data: { final res = await _apiClient.post(
'username': email, '/auth/password-login',
'password': password, data: {'username': email, 'password': password},
}, fromJson: (d) { fromJson: (d) {
final user = d['user']; final user = d['user'];
return User( return User(
id: user['id'].toString(), id: user['id'].toString(),
username: user['username'] ?? user['email'], username: user['username'] ?? user['email'],
email: user['email'], email: user['email'],
createdAt: DateTime.parse(user['createdAt'] ?? DateTime.now().toIso8601String()), createdAt: DateTime.parse(
user['createdAt'] ?? DateTime.now().toIso8601String(),
),
);
},
); );
});
return res; return res;
} }
@@ -34,7 +37,9 @@ class HttpAuthRepository implements AuthRepository {
id: user['id'].toString(), id: user['id'].toString(),
username: user['username'] ?? user['email'], username: user['username'] ?? user['email'],
email: user['email'], email: user['email'],
createdAt: DateTime.parse(user['createdAt'] ?? DateTime.now().toIso8601String()), createdAt: DateTime.parse(
user['createdAt'] ?? DateTime.now().toIso8601String(),
),
); );
} }
} catch (_) {} } catch (_) {}

View File

@@ -35,12 +35,20 @@ class HttpFileRepository implements FileRepository {
} }
@override @override
Future<void> createFolder(String orgId, String parentPath, String folderName) async { Future<void> createFolder(
String orgId,
String parentPath,
String folderName,
) async {
await _fileService.createFolder(orgId, parentPath, folderName); await _fileService.createFolder(orgId, parentPath, folderName);
} }
@override @override
Future<void> moveFile(String orgId, String sourcePath, String targetPath) async { Future<void> moveFile(
String orgId,
String sourcePath,
String targetPath,
) async {
throw UnimplementedError(); throw UnimplementedError();
} }
@@ -53,21 +61,33 @@ class HttpFileRepository implements FileRepository {
Future<List<FileItem>> searchFiles(String orgId, String query) async { Future<List<FileItem>> searchFiles(String orgId, String query) async {
// Not yet parameterized on API side; fallback to client-side filter // Not yet parameterized on API side; fallback to client-side filter
final files = await getFiles(orgId, '/'); final files = await getFiles(orgId, '/');
return files.where((f) => f.name.toLowerCase().contains(query.toLowerCase())).toList(); return files
.where((f) => f.name.toLowerCase().contains(query.toLowerCase()))
.toList();
} }
@override @override
Future<ViewerSession> requestViewerSession(String orgId, String fileId) async { Future<ViewerSession> requestViewerSession(
String orgId,
String fileId,
) async {
return await _fileService.requestViewerSession(orgId, fileId); return await _fileService.requestViewerSession(orgId, fileId);
} }
@override @override
Future<EditorSession> requestEditorSession(String orgId, String fileId) async { Future<EditorSession> requestEditorSession(
String orgId,
String fileId,
) async {
return await _fileService.requestEditorSession(orgId, fileId); return await _fileService.requestEditorSession(orgId, fileId);
} }
@override @override
Future<void> saveAnnotations(String orgId, String fileId, List<Annotation> annotations) async { Future<void> saveAnnotations(
String orgId,
String fileId,
List<Annotation> annotations,
) async {
await _fileService.saveAnnotations(orgId, fileId, annotations); await _fileService.saveAnnotations(orgId, fileId, annotations);
} }
} }

View File

@@ -48,9 +48,7 @@ class FileService {
Future<void> uploadFile(String orgId, FileItem file) async { Future<void> uploadFile(String orgId, FileItem file) async {
// If bytes or localPath available, send multipart upload with field 'file' // If bytes or localPath available, send multipart upload with field 'file'
final Map<String, dynamic> fields = { final Map<String, dynamic> fields = {'path': file.path};
'path': file.path,
};
FormData formData; FormData formData;
if (file.bytes != null) { if (file.bytes != null) {
formData = FormData.fromMap({ formData = FormData.fromMap({
@@ -74,24 +72,44 @@ class FileService {
await _apiClient.post('/user/files', data: data, fromJson: (d) => null); await _apiClient.post('/user/files', data: data, fromJson: (d) => null);
return; return;
} }
await _apiClient.post('/orgs/$orgId/files', data: data, fromJson: (d) => null); await _apiClient.post(
'/orgs/$orgId/files',
data: data,
fromJson: (d) => null,
);
return; return;
} }
if (orgId.isEmpty) { if (orgId.isEmpty) {
await _apiClient.post('/user/files', data: formData, fromJson: (d) => null); await _apiClient.post(
'/user/files',
data: formData,
fromJson: (d) => null,
);
return; return;
} }
await _apiClient.post('/orgs/$orgId/files', data: formData, fromJson: (d) => null); await _apiClient.post(
'/orgs/$orgId/files',
data: formData,
fromJson: (d) => null,
);
} }
Future<void> deleteFile(String orgId, String path) async { Future<void> deleteFile(String orgId, String path) async {
final data = {'path': path}; final data = {'path': path};
if (orgId.isEmpty) { if (orgId.isEmpty) {
await _apiClient.post('/user/files/delete', data: data, fromJson: (d) => null); await _apiClient.post(
'/user/files/delete',
data: data,
fromJson: (d) => null,
);
return; return;
} }
await _apiClient.post('/orgs/$orgId/files/delete', data: data, fromJson: (d) => null); await _apiClient.post(
'/orgs/$orgId/files/delete',
data: data,
fromJson: (d) => null,
);
} }
Future<void> createFolder( Future<void> createFolder(
@@ -99,7 +117,9 @@ class FileService {
String parentPath, String parentPath,
String folderName, String folderName,
) async { ) async {
final path = parentPath.endsWith('/') ? '$parentPath$folderName' : '$parentPath/$folderName'; final path = parentPath.endsWith('/')
? '$parentPath$folderName'
: '$parentPath/$folderName';
final data = { final data = {
'name': folderName, 'name': folderName,
'path': path, 'path': path,
@@ -110,7 +130,11 @@ class FileService {
await _apiClient.post('/user/files', data: data, fromJson: (d) => null); await _apiClient.post('/user/files', data: data, fromJson: (d) => null);
return; return;
} }
await _apiClient.post('/orgs/$orgId/files', data: data, fromJson: (d) => null); await _apiClient.post(
'/orgs/$orgId/files',
data: data,
fromJson: (d) => null,
);
} }
Future<void> moveFile( Future<void> moveFile(

View File

@@ -2,13 +2,13 @@ package http
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
"fmt"
"go.b0esche.cloud/backend/internal/audit" "go.b0esche.cloud/backend/internal/audit"
"go.b0esche.cloud/backend/internal/auth" "go.b0esche.cloud/backend/internal/auth"