fix: bind ride backup to shared Firebase identity and prevent GitHub routing
This commit is contained in:
parent
272a2b56ee
commit
f31e0b8eaa
|
|
@ -36,10 +36,10 @@ class GitHubUploadResult {
|
|||
|
||||
/// Compatibility facade for the historical ride-detail sync service.
|
||||
///
|
||||
/// MotorSignal cloud backup is Firebase Authentication + Firestore + R2.
|
||||
/// The old GitHub PAT exporter remains available only through the explicit
|
||||
/// `uploadRideToGitHub` developer/export path and is never used by the normal
|
||||
/// History -> Upload Now action.
|
||||
/// Normal MotorSignal cloud backup is Firebase Authentication + Firestore + R2.
|
||||
/// The historical GitHub PAT exporter remains available only through the
|
||||
/// explicit `uploadRideToGitHub` developer/export path and is never used by
|
||||
/// the normal History -> Upload Now action.
|
||||
class GitHubSyncService extends ChangeNotifier {
|
||||
final AppDatabase _db;
|
||||
final GitHubAuthService _githubAuth;
|
||||
|
|
@ -51,12 +51,17 @@ class GitHubSyncService extends ChangeNotifier {
|
|||
String _statusMessage = '';
|
||||
final Set<int> _uploadQueue = {};
|
||||
|
||||
/// Keeps the historical constructor compatible with tests/callers that pass
|
||||
/// an HTTP client as the optional fourth argument. Production additionally
|
||||
/// supplies the shared Firebase AuthService as the fifth argument.
|
||||
GitHubSyncService(
|
||||
this._db,
|
||||
this._githubAuth,
|
||||
this._authService,
|
||||
this._prefs, [http.Client? client],
|
||||
) : _client = client ?? http.Client();
|
||||
this._prefs, [
|
||||
http.Client? client,
|
||||
AuthService? authService,
|
||||
]) : _authService = authService ?? FirebaseAuthService(),
|
||||
_client = client ?? http.Client();
|
||||
|
||||
GitHubUploadState get state => _state;
|
||||
String get statusMessage => _statusMessage;
|
||||
|
|
@ -69,21 +74,18 @@ class GitHubSyncService extends ChangeNotifier {
|
|||
}
|
||||
|
||||
bool isRideUploaded(int rideId) {
|
||||
final scoped = _userScopedKey('motorcloud_uploaded_ride', rideId);
|
||||
if (scoped == null) return false;
|
||||
return _prefs.getBool(scoped) ?? false;
|
||||
final key = _userScopedKey('motorcloud_uploaded_ride', rideId);
|
||||
return key != null && (_prefs.getBool(key) ?? false);
|
||||
}
|
||||
|
||||
String? getRideCommitSha(int rideId) {
|
||||
final scoped = _userScopedKey('motorcloud_ride_remote_id', rideId);
|
||||
if (scoped == null) return null;
|
||||
return _prefs.getString(scoped);
|
||||
final key = _userScopedKey('motorcloud_ride_remote_id', rideId);
|
||||
return key == null ? null : _prefs.getString(key);
|
||||
}
|
||||
|
||||
String? getRideUploadTimestamp(int rideId) {
|
||||
final scoped = _userScopedKey('motorcloud_uploaded_at_ride', rideId);
|
||||
if (scoped == null) return null;
|
||||
return _prefs.getString(scoped);
|
||||
final key = _userScopedKey('motorcloud_uploaded_at_ride', rideId);
|
||||
return key == null ? null : _prefs.getString(key);
|
||||
}
|
||||
|
||||
void queueRideForUpload(int rideId) {
|
||||
|
|
@ -105,23 +107,23 @@ class GitHubSyncService extends ChangeNotifier {
|
|||
|
||||
/// Normal History -> Upload Now operation.
|
||||
///
|
||||
/// This deliberately ignores any configured GitHub PAT. A user's ride must
|
||||
/// be written to that user's MotorCloud account, not to a public developer
|
||||
/// repository. Authentication and ownership are enforced by Firebase/R2.
|
||||
/// Deliberately ignores any configured GitHub PAT. A user's ride must be
|
||||
/// written to that user's MotorCloud account, never to the developer's
|
||||
/// public repository.
|
||||
Future<GitHubUploadResult> uploadRide(int rideId, {bool isManual = false}) async {
|
||||
return _uploadToMotorCloud(rideId);
|
||||
}
|
||||
|
||||
/// Explicit legacy/developer export. Not used by the normal ride UI.
|
||||
Future<GitHubUploadResult> uploadRideToGitHub(int rideId) async {
|
||||
final githubToken = _githubAuth.getToken();
|
||||
if (githubToken == null || githubToken.isEmpty) {
|
||||
final token = _githubAuth.getToken();
|
||||
if (token == null || token.isEmpty) {
|
||||
return GitHubUploadResult(
|
||||
success: false,
|
||||
message: 'GitHub export requires an explicitly configured GitHub token.',
|
||||
);
|
||||
}
|
||||
return _uploadToGitHub(rideId, githubToken);
|
||||
return _uploadToGitHub(rideId, token);
|
||||
}
|
||||
|
||||
Future<GitHubUploadResult> _uploadToMotorCloud(int rideId) async {
|
||||
|
|
@ -137,7 +139,12 @@ class GitHubSyncService extends ChangeNotifier {
|
|||
_state = GitHubUploadState.success;
|
||||
_statusMessage = 'Ride #$rideId is already backed up to your MotorCloud account.';
|
||||
notifyListeners();
|
||||
return GitHubUploadResult(success: true, message: _statusMessage, commitSha: getRideCommitSha(rideId), targetPath: 'MotorCloud');
|
||||
return GitHubUploadResult(
|
||||
success: true,
|
||||
message: _statusMessage,
|
||||
commitSha: getRideCommitSha(rideId),
|
||||
targetPath: 'MotorCloud',
|
||||
);
|
||||
}
|
||||
|
||||
_state = GitHubUploadState.uploading;
|
||||
|
|
@ -145,25 +152,25 @@ class GitHubSyncService extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
|
||||
try {
|
||||
final provider = FirebaseSyncProvider(
|
||||
db: _db,
|
||||
authService: _authService,
|
||||
);
|
||||
final result = await provider.uploadRide(
|
||||
SyncItem(
|
||||
localRideId: rideId,
|
||||
providerId: 'firebase',
|
||||
createdAt: DateTime.now(),
|
||||
),
|
||||
);
|
||||
final provider = FirebaseSyncProvider(db: _db, authService: _authService);
|
||||
final result = await provider.uploadRide(SyncItem(
|
||||
localRideId: rideId,
|
||||
providerId: 'firebase',
|
||||
createdAt: DateTime.now(),
|
||||
));
|
||||
|
||||
if (result.success) {
|
||||
final uploadedKey = _userScopedKey('motorcloud_uploaded_ride', rideId)!;
|
||||
final timestampKey = _userScopedKey('motorcloud_uploaded_at_ride', rideId)!;
|
||||
final remoteIdKey = _userScopedKey('motorcloud_ride_remote_id', rideId)!;
|
||||
await _prefs.setBool(uploadedKey, true);
|
||||
await _prefs.setString(timestampKey, DateTime.now().toIso8601String());
|
||||
if (result.remoteId != null) await _prefs.setString(remoteIdKey, result.remoteId!);
|
||||
await _prefs.setBool(_userScopedKey('motorcloud_uploaded_ride', rideId)!, true);
|
||||
await _prefs.setString(
|
||||
_userScopedKey('motorcloud_uploaded_at_ride', rideId)!,
|
||||
DateTime.now().toIso8601String(),
|
||||
);
|
||||
if (result.remoteId != null) {
|
||||
await _prefs.setString(
|
||||
_userScopedKey('motorcloud_ride_remote_id', rideId)!,
|
||||
result.remoteId!,
|
||||
);
|
||||
}
|
||||
_uploadQueue.remove(rideId);
|
||||
_state = GitHubUploadState.success;
|
||||
_statusMessage = 'Ride #$rideId backed up to your MotorCloud account';
|
||||
|
|
@ -323,7 +330,7 @@ class GitHubSyncService extends ChangeNotifier {
|
|||
final githubSyncServiceProvider = ChangeNotifierProvider<GitHubSyncService>((ref) {
|
||||
final db = ref.watch(databaseProvider);
|
||||
final githubAuth = ref.watch(githubAuthServiceProvider);
|
||||
final authService = ref.watch(authServiceProvider);
|
||||
final prefs = ref.watch(sharedPreferencesProvider);
|
||||
return GitHubSyncService(db, githubAuth, authService, prefs);
|
||||
final authService = ref.watch(authServiceProvider);
|
||||
return GitHubSyncService(db, githubAuth, prefs, null, authService);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue