feat: deploy infrastructure + disk/drive, calendar, presentation, workspaces, onboarding, demo user
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../core/api/client.dart';
|
||||
import '../core/api/endpoints.dart';
|
||||
import '../core/api/exceptions.dart';
|
||||
import '../models/auth.dart';
|
||||
|
||||
enum AuthStatus { initial, authenticated, unauthenticated, loading }
|
||||
|
||||
class AuthState {
|
||||
final AuthStatus status;
|
||||
final User? user;
|
||||
final String? error;
|
||||
final bool needsTwoFactor;
|
||||
|
||||
AuthState({
|
||||
this.status = AuthStatus.initial,
|
||||
this.user,
|
||||
this.error,
|
||||
this.needsTwoFactor = false,
|
||||
});
|
||||
|
||||
AuthState copyWith({
|
||||
AuthStatus? status,
|
||||
User? user,
|
||||
String? error,
|
||||
bool? needsTwoFactor,
|
||||
}) =>
|
||||
AuthState(
|
||||
status: status ?? this.status,
|
||||
user: user ?? this.user,
|
||||
error: error,
|
||||
needsTwoFactor: needsTwoFactor ?? this.needsTwoFactor,
|
||||
);
|
||||
}
|
||||
|
||||
class AuthNotifier extends StateNotifier<AuthState> {
|
||||
final ApiClient _api;
|
||||
|
||||
AuthNotifier(this._api) : super(AuthState()) {
|
||||
_checkAuth();
|
||||
}
|
||||
|
||||
Future<void> _checkAuth() async {
|
||||
final token = await _api.getAccessToken();
|
||||
if (token != null) {
|
||||
state = state.copyWith(status: AuthStatus.authenticated);
|
||||
} else {
|
||||
state = state.copyWith(status: AuthStatus.unauthenticated);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> login(String email, String password) async {
|
||||
state = state.copyWith(status: AuthStatus.loading, error: null);
|
||||
try {
|
||||
final response = await _api.post(Endpoints.login, data: {
|
||||
'email': email,
|
||||
'password': password,
|
||||
});
|
||||
final authResponse = AuthResponse.fromJson(
|
||||
response.data as Map<String, dynamic>);
|
||||
if (authResponse.user.isTwoFactorEnabled) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.unauthenticated,
|
||||
needsTwoFactor: true,
|
||||
);
|
||||
return;
|
||||
}
|
||||
await _api.saveTokens(
|
||||
authResponse.accessToken, authResponse.refreshToken);
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.authenticated,
|
||||
user: authResponse.user,
|
||||
);
|
||||
} on ApiException catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.unauthenticated,
|
||||
error: e.message,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> register(String email, String password, String name) async {
|
||||
state = state.copyWith(status: AuthStatus.loading, error: null);
|
||||
try {
|
||||
final response = await _api.post(Endpoints.register, data: {
|
||||
'email': email,
|
||||
'password': password,
|
||||
'name': name,
|
||||
});
|
||||
final authResponse = AuthResponse.fromJson(
|
||||
response.data as Map<String, dynamic>);
|
||||
await _api.saveTokens(
|
||||
authResponse.accessToken, authResponse.refreshToken);
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.authenticated,
|
||||
user: authResponse.user,
|
||||
);
|
||||
} on ApiException catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.unauthenticated,
|
||||
error: e.message,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> verifyTwoFactor(String code) async {
|
||||
state = state.copyWith(status: AuthStatus.loading, error: null);
|
||||
try {
|
||||
final response = await _api.post(Endpoints.twoFactor, data: {
|
||||
'code': code,
|
||||
});
|
||||
final authResponse = AuthResponse.fromJson(
|
||||
response.data as Map<String, dynamic>);
|
||||
await _api.saveTokens(
|
||||
authResponse.accessToken, authResponse.refreshToken);
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.authenticated,
|
||||
user: authResponse.user,
|
||||
needsTwoFactor: false,
|
||||
);
|
||||
} on ApiException catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.unauthenticated,
|
||||
error: e.message,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
await _api.clearTokens();
|
||||
state = AuthState(status: AuthStatus.unauthenticated);
|
||||
}
|
||||
|
||||
Future<void> forgotPassword(String email) async {
|
||||
state = state.copyWith(status: AuthStatus.loading, error: null);
|
||||
try {
|
||||
await _api.post(Endpoints.forgotPassword, data: {'email': email});
|
||||
state = state.copyWith(status: AuthStatus.unauthenticated);
|
||||
} on ApiException catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.unauthenticated, error: e.message);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> resetPassword(String token, String password) async {
|
||||
state = state.copyWith(status: AuthStatus.loading, error: null);
|
||||
try {
|
||||
await _api.post(Endpoints.resetPassword, data: {
|
||||
'token': token,
|
||||
'password': password,
|
||||
});
|
||||
state = state.copyWith(status: AuthStatus.unauthenticated);
|
||||
} on ApiException catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.unauthenticated, error: e.message);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> getOAuthUrl(String provider) async {
|
||||
try {
|
||||
final response = await _api.get('${Endpoints.oauth}/$provider');
|
||||
return response.data['url'] as String?;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void clearError() {
|
||||
state = state.copyWith(error: null);
|
||||
}
|
||||
}
|
||||
|
||||
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
|
||||
final api = ref.read(apiClientProvider);
|
||||
return AuthNotifier(api);
|
||||
});
|
||||
Reference in New Issue
Block a user