Enhance session restoration and add user file viewer endpoint
This commit is contained in:
@@ -52,12 +52,13 @@ class MainApp extends StatefulWidget {
|
||||
class _MainAppState extends State<MainApp> {
|
||||
final _sessionBloc = SessionBloc();
|
||||
late final AuthBloc _authBloc;
|
||||
late final Future<void> _restoreFuture;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Restore session from persistent storage early so ApiClient has token if present
|
||||
SessionBloc.restoreSession(_sessionBloc);
|
||||
_restoreFuture = SessionBloc.restoreSession(_sessionBloc);
|
||||
// Configure DI to use HTTP repositories
|
||||
configureDependencies(_sessionBloc);
|
||||
|
||||
@@ -78,9 +79,22 @@ class _MainAppState extends State<MainApp> {
|
||||
ActivityBloc(ActivityApi(ApiClient(_sessionBloc))),
|
||||
),
|
||||
],
|
||||
child: MaterialApp.router(
|
||||
routerConfig: _router,
|
||||
theme: AppTheme.darkTheme,
|
||||
child: FutureBuilder<void>(
|
||||
future: _restoreFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return MaterialApp(
|
||||
theme: AppTheme.darkTheme,
|
||||
home: const Scaffold(
|
||||
body: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MaterialApp.router(
|
||||
routerConfig: _router,
|
||||
theme: AppTheme.darkTheme,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -168,11 +168,14 @@ class FileService {
|
||||
String orgId,
|
||||
String fileId,
|
||||
) async {
|
||||
if (orgId.isEmpty || fileId.isEmpty) {
|
||||
throw Exception('OrgId and fileId cannot be empty');
|
||||
if (fileId.isEmpty) {
|
||||
throw Exception('fileId cannot be empty');
|
||||
}
|
||||
final path = orgId.isEmpty
|
||||
? '/user/files/$fileId/view'
|
||||
: '/orgs/$orgId/files/$fileId/view';
|
||||
return await _apiClient.get(
|
||||
'/orgs/$orgId/files/$fileId/view',
|
||||
path,
|
||||
fromJson: (data) => ViewerSession.fromJson(data),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,6 +81,10 @@ func NewRouter(cfg *config.Config, db *database.DB, jwtManager *jwt.Manager, aut
|
||||
r.Get("/user/files", func(w http.ResponseWriter, req *http.Request) {
|
||||
userFilesHandler(w, req, db)
|
||||
})
|
||||
// User file viewer
|
||||
r.Get("/user/files/{fileId}/view", func(w http.ResponseWriter, req *http.Request) {
|
||||
userViewerHandler(w, req, db, auditLogger)
|
||||
})
|
||||
// Download user file
|
||||
r.Get("/user/files/download", func(w http.ResponseWriter, req *http.Request) {
|
||||
downloadUserFileHandler(w, req, db, storageClient)
|
||||
@@ -382,6 +386,42 @@ func viewerHandler(w http.ResponseWriter, r *http.Request, db *database.DB, audi
|
||||
json.NewEncoder(w).Encode(session)
|
||||
}
|
||||
|
||||
// userViewerHandler serves a viewer session for personal workspace files
|
||||
func userViewerHandler(w http.ResponseWriter, r *http.Request, db *database.DB, auditLogger *audit.Logger) {
|
||||
userIDStr, _ := middleware.GetUserID(r.Context())
|
||||
userID, _ := uuid.Parse(userIDStr)
|
||||
fileId := chi.URLParam(r, "fileId")
|
||||
|
||||
// For now, return a synthetic viewer session similar to org viewer
|
||||
session := struct {
|
||||
ViewUrl string `json:"viewUrl"`
|
||||
Capabilities struct {
|
||||
CanEdit bool `json:"canEdit"`
|
||||
CanAnnotate bool `json:"canAnnotate"`
|
||||
IsPdf bool `json:"isPdf"`
|
||||
} `json:"capabilities"`
|
||||
ExpiresAt string `json:"expiresAt"`
|
||||
}{
|
||||
ViewUrl: "https://view.example.com/" + fileId,
|
||||
Capabilities: struct {
|
||||
CanEdit bool `json:"canEdit"`
|
||||
CanAnnotate bool `json:"canAnnotate"`
|
||||
IsPdf bool `json:"isPdf"`
|
||||
}{
|
||||
CanEdit: false,
|
||||
CanAnnotate: true,
|
||||
IsPdf: strings.HasSuffix(strings.ToLower(fileId), ".pdf"),
|
||||
},
|
||||
ExpiresAt: time.Now().Add(15 * time.Minute).UTC().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
// Optionally log activity without org id
|
||||
db.LogActivity(r.Context(), userID, uuid.Nil, &fileId, "view_user_file", map[string]interface{}{})
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(session)
|
||||
}
|
||||
|
||||
func editorHandler(w http.ResponseWriter, r *http.Request, db *database.DB, auditLogger *audit.Logger) {
|
||||
userIDStr, _ := middleware.GetUserID(r.Context())
|
||||
userID, _ := uuid.Parse(userIDStr)
|
||||
|
||||
Reference in New Issue
Block a user