Skip to content

Commit

Permalink
and a comma
Browse files Browse the repository at this point in the history
  • Loading branch information
fremartini committed Nov 23, 2023
1 parent 058d48c commit ec8f80d
Show file tree
Hide file tree
Showing 27 changed files with 301 additions and 371 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ class AuthenticationLocalDataSource {
email: user.email,
token: token,
encodedPasscode: user.encodedPasscode,
lastLogin: user.lastLogin,
sessionTimeout: user.sessionTimeout,
);

await saveAuthenticatedUser(model);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,77 +1,25 @@
import 'package:coffeecard/features/authentication/domain/entities/authenticated_user.dart';
import 'package:fpdart/fpdart.dart';

class AuthenticatedUserModel extends AuthenticatedUser {
const AuthenticatedUserModel({
required super.email,
required super.token,
required super.encodedPasscode,
required super.lastLogin,
required super.sessionTimeout,
});

factory AuthenticatedUserModel.fromJson(Map<String, dynamic> json) {
final lastLogin =
_nullOrValue<DateTime>(json, 'last_login', DateTime.parse);
final sessionTimeout = _nullOrValue<Duration>(
json,
'session_timeout',
_parseDuration,
);

return AuthenticatedUserModel(
email: json['email'] as String,
token: json['token'] as String,
encodedPasscode: json['passcode'] as String,
lastLogin: lastLogin,
sessionTimeout: sessionTimeout,
);
}

static String? _optionToString<T>(Option<T> option) {
return option.match(() => 'null', (value) => value.toString());
}

Map<String, dynamic> toJson() {
return {
'email': email,
'token': token,
'passcode': encodedPasscode,
'last_login': _optionToString(lastLogin),
'session_timeout': _optionToString(sessionTimeout),
};
}

static Option<T> _nullOrValue<T>(
Map<String, dynamic> m,
String key,
T Function(String) callback,
) {
if (!m.containsKey(key)) {
return none();
}

final val = m[key] as String;

if (val == 'null') {
return none();
}

return Some(callback(val));
}

static Duration _parseDuration(String s) {
int hours = 0;
int minutes = 0;

final parts = s.split(':');
if (parts.length > 2) {
hours = int.parse(parts[parts.length - 3]);
}
if (parts.length > 1) {
minutes = int.parse(parts[parts.length - 2]);
}

return Duration(hours: hours, minutes: minutes);
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
import 'package:equatable/equatable.dart';
import 'package:fpdart/fpdart.dart';

class AuthenticatedUser extends Equatable {
final String email;
final String token;
final String encodedPasscode;
final Option<DateTime> lastLogin;
final Option<Duration> sessionTimeout;

const AuthenticatedUser({
required this.email,
required this.token,
required this.encodedPasscode,
required this.lastLogin,
required this.sessionTimeout,
});

@override
List<Object?> get props => [
email,
token,
encodedPasscode,
lastLogin,
sessionTimeout,
];
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:coffeecard/features/authentication/data/datasources/authentication_local_data_source.dart';
import 'package:coffeecard/features/authentication/data/models/authenticated_user_model.dart';
import 'package:fpdart/fpdart.dart';

class SaveAuthenticatedUser {
final AuthenticationLocalDataSource dataSource;
Expand All @@ -11,16 +10,12 @@ class SaveAuthenticatedUser {
required String email,
required String token,
required String encodedPasscode,
required Option<DateTime> lastLogin,
required Option<Duration> sessionTimeout,
}) async {
return dataSource.saveAuthenticatedUser(
AuthenticatedUserModel(
email: email,
token: token,
encodedPasscode: encodedPasscode,
lastLogin: lastLogin,
sessionTimeout: sessionTimeout,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import 'package:coffeecard/features/authentication/domain/entities/authenticated
import 'package:coffeecard/features/authentication/domain/usecases/clear_authenticated_user.dart';
import 'package:coffeecard/features/authentication/domain/usecases/get_authenticated_user.dart';
import 'package:coffeecard/features/authentication/domain/usecases/save_authenticated_user.dart';
import 'package:coffeecard/features/session/domain/usecases/get_session_details.dart';
import 'package:coffeecard/features/session/domain/usecases/save_session_details.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fpdart/fpdart.dart';
Expand All @@ -16,30 +18,39 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
final ClearAuthenticatedUser clearAuthenticatedUser;
final SaveAuthenticatedUser saveAuthenticatedUser;
final GetAuthenticatedUser getAuthenticatedUser;
final GetSessionDetails getSessionDetails;
final SaveSessionDetails saveSessionDetails;
final DateService dateService;

AuthenticationCubit({
required this.clearAuthenticatedUser,
required this.saveAuthenticatedUser,
required this.getAuthenticatedUser,
required this.getSessionDetails,
required this.saveSessionDetails,
required this.dateService,
}) : super(const AuthenticationState._());

Future<void> appStarted() async {
final authenticatedUser = await getAuthenticatedUser();
final sessionDetails = await getSessionDetails();

authenticatedUser.match(
() => emit(const AuthenticationState.unauthenticated()),
(authenticatedUser) {
final sessionExpired = _isSessionExpired(
authenticatedUser.lastLogin,
authenticatedUser.sessionTimeout,
);
(authenticatedUser) async {
sessionDetails.map(
(sessionDetails) async {
final sessionExpired = _isSessionExpired(
sessionDetails.lastLogin,
sessionDetails.sessionTimeout,
);

if (sessionExpired) {
emit(AuthenticationState.reauthenticated(authenticatedUser));
return;
}
if (sessionExpired) {
await unauthenticated();
return;
}
},
);

emit(AuthenticationState.authenticated(authenticatedUser));
},
Expand All @@ -48,13 +59,17 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {

bool _isSessionExpired(
Option<DateTime> lastLogin,
Option<Duration> sessionTimeout,
Option<Duration?> sessionTimeout,
) {
return lastLogin.match(
() => false,
(lastLogin) => sessionTimeout.match(
() => false,
(sessionTimeout) {
if (sessionTimeout == null) {
return false;
}

final now = dateService.currentDateTime;
final difference = now.difference(lastLogin);
return difference > sessionTimeout;
Expand All @@ -68,14 +83,24 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
String encodedPasscode,
String token,
) async {
final now = dateService.currentDateTime;

await saveAuthenticatedUser(
email: email,
token: token,
encodedPasscode: encodedPasscode,
lastLogin: some(now),
sessionTimeout: none(),
);

final sessionDetails = await getSessionDetails();

final now = some(dateService.currentDateTime);
sessionDetails.match(
() async => await saveSessionDetails(
lastLogin: now,
sessionTimeout: none(),
),
(sessionDetails) async => await saveSessionDetails(
lastLogin: now,
sessionTimeout: sessionDetails.sessionTimeout,
),
);

emit(
Expand All @@ -84,8 +109,6 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
token: token,
email: email,
encodedPasscode: encodedPasscode,
lastLogin: some(now),
sessionTimeout: none(),
),
),
);
Expand All @@ -95,21 +118,4 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
await clearAuthenticatedUser();
emit(const AuthenticationState.unauthenticated());
}

Future<void> saveSessionTimeout(Duration? duration) async {
final user = await getAuthenticatedUser();

user.match(
() => null,
(user) async {
await saveAuthenticatedUser(
email: user.email,
token: user.token,
encodedPasscode: user.encodedPasscode,
lastLogin: user.lastLogin,
sessionTimeout: optionOf(duration),
);
},
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ class AuthenticationState extends Equatable {
authenticatedUser: authenticatedUser,
);

const AuthenticationState.reauthenticated(AuthenticatedUser authenticatedUser)
: this._(
status: AuthenticationStatus.reauthenticated,
authenticatedUser: authenticatedUser,
);

const AuthenticationState.unauthenticated()
: this._(status: AuthenticationStatus.unauthenticated);

Expand All @@ -42,12 +36,10 @@ enum AuthenticationStatus {
unknown,
authenticated,
unauthenticated,
reauthenticated
}

extension AuthenticationStatusIs on AuthenticationStatus {
bool get isUnknown => this == AuthenticationStatus.unknown;
bool get isAuthenticated => this == AuthenticationStatus.authenticated;
bool get isUnauthenticated => this == AuthenticationStatus.unauthenticated;
bool get isReauthenticated => this == AuthenticationStatus.reauthenticated;
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ class AccountRemoteDataSource {
email: email,
encodedPasscode: encodedPasscode,
token: result.token!,
lastLogin: none(),
sessionTimeout: none(),
),
),
);
Expand Down
Loading

0 comments on commit ec8f80d

Please sign in to comment.