Last active
April 14, 2020 11:44
-
-
Save roboncode/cd82ee61304fff3e0e110daade4b796a to your computer and use it in GitHub Desktop.
Dart - Bloc Auth Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
class ServiceRespository { | |
Future<String> authenticate(String username, String password) { | |
if(username == "admin" && password == "admin") { | |
return Future<String>.delayed(Duration(milliseconds: 2000)) | |
.then((_) => "abc"); | |
} | |
return Future<String>.delayed(Duration(milliseconds: 1000)) | |
.then((_) => throw "invalid credentials"); | |
} | |
Future clearSession() { | |
return Future<String>.delayed(Duration(milliseconds: 100)); | |
} | |
} | |
class AuthEvent {} | |
class UnauthorizedEvent extends AuthEvent { | |
final String message; | |
UnauthorizedEvent(this.message); | |
} | |
class AuthorizedEvent extends AuthEvent { | |
final String token; | |
AuthorizedEvent(this.token); | |
} | |
class AuthorizingEvent extends AuthEvent {} | |
class LogoutEvent extends AuthEvent {} | |
class ErrorEvent extends AuthEvent{ | |
final String message; | |
ErrorEvent({this.message = "unknown error"}); | |
} | |
class AuthState {} | |
class GuestState extends AuthState {} | |
class UnauthorizedState extends AuthState { | |
final String message; | |
UnauthorizedState({this.message}); | |
} | |
class AuthorizedState extends AuthState { | |
final String token; | |
AuthorizedState(this.token); | |
} | |
class AuthorizingState extends AuthState {} | |
class ErrorState extends AuthState{ | |
final String message; | |
ErrorState(this.message); | |
} | |
class AuthTransition { | |
final AuthState currentState; | |
final AuthEvent event; | |
final AuthState nextState; | |
AuthTransition(this.currentState, this.event, this.nextState); | |
toString() { | |
return 'Transition { currentState: ${currentState.runtimeType}, event: ${event.runtimeType}, nextState: ${nextState.runtimeType} }'; | |
} | |
} | |
class AuthBloc { | |
ServiceRespository _repository; | |
AuthState _state = GuestState(); | |
get state => _state; | |
final _stateController = StreamController<AuthState>(); | |
Stream<AuthState> get auth => _stateController.stream; | |
final _eventController = StreamController<AuthEvent>(); | |
get add => _eventController.sink.add; | |
AuthBloc(ServiceRespository repository) { | |
this._repository = repository; | |
_eventController.stream.listen(_mapEventToState); | |
} | |
Future login(String username, String password) async { | |
add(AuthorizingEvent()); | |
try { | |
String token = await _repository.authenticate(username, password); | |
add(AuthorizedEvent(token)); | |
} catch(e) { | |
add(UnauthorizedEvent(e)); | |
} | |
} | |
Future logout() async { | |
await _repository.clearSession(); | |
add(LogoutEvent()); | |
} | |
_mapEventToState(AuthEvent event) { | |
AuthState currentState = _state; | |
if(event is UnauthorizedEvent) { | |
_state = UnauthorizedState(message: event.message); | |
onTransition(AuthTransition(currentState, event, _state)); | |
_stateController.sink.add(_state); | |
_state = GuestState(); | |
} else if (event is AuthorizedEvent) { | |
_state = AuthorizedState(event.token); | |
} else if (event is AuthorizingEvent) { | |
_state = AuthorizingState(); | |
} else if (event is LogoutEvent) { | |
_state = GuestState(); | |
} else { | |
_state = ErrorState("invalid event"); | |
} | |
if(currentState.toString() != state.toString()) { | |
onTransition(AuthTransition(currentState, event, _state)); | |
} | |
_stateController.sink.add(_state); | |
} | |
void onTransition(AuthTransition transition) { | |
print(transition); | |
// print('you are here ${transition.currentState}'); | |
} | |
void close() { | |
_stateController.close(); | |
_eventController.close(); | |
} | |
} | |
AuthBloc startListen() { | |
final AuthBloc authBloc = AuthBloc(ServiceRespository()); | |
authBloc.auth.listen((AuthState state) { | |
print(state); | |
if (state is AuthorizedState) { | |
print("Auth token is " + state.token); | |
} else if (state is UnauthorizedState) { | |
print("Unauthorized: " + state.message); | |
} | |
}).onError((err) => print(err)); | |
return authBloc; | |
} | |
void stopListten(AuthBloc authBloc) { | |
authBloc.close(); | |
} | |
void main() async { | |
AuthBloc authBloc = startListen(); | |
print(authBloc.state); | |
// print("login with valid credentials"); | |
await authBloc.login("admin", "admin"); | |
// print("logout"); | |
await authBloc.logout(); | |
// print("login with invalid credentials"); | |
await authBloc.login("demo", "demo"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Not really intending to use this, just wanted to understand Bloc better by creating a Bloc from scratch. I will be using ...
https://bloclibrary.dev/
YouTube video from author: https://www.youtube.com/watch?v=knMvKPKBzGE