diff --git a/flutter-ory-network/lib/blocs/auth/auth_bloc.dart b/flutter-ory-network/lib/blocs/auth/auth_bloc.dart index 4ca09ad5..71727cbe 100644 --- a/flutter-ory-network/lib/blocs/auth/auth_bloc.dart +++ b/flutter-ory-network/lib/blocs/auth/auth_bloc.dart @@ -30,7 +30,8 @@ class AuthBloc extends Bloc { } _onAddSession(AddSession event, Emitter emit) { - emit(AuthState.authenticated(session: event.session)); + emit(AuthState.authenticated( + session: event.session, conditions: event.conditions)); } _onChangeAuthStatus(ChangeAuthStatus event, Emitter emit) { @@ -38,7 +39,7 @@ class AuthBloc extends Bloc { case AuthStatus.unauthenticated: emit(const AuthState.unauthenticated()); case AuthStatus.aal2Requested: - emit(const AuthState.aal2Requested()); + emit(AuthState.aal2Requested(conditions: event.conditions)); default: emit(state); } @@ -52,11 +53,12 @@ class AuthBloc extends Bloc { final session = await repository.getCurrentSessionInformation(); - emit(AuthState.authenticated(session: session)); + emit(AuthState.authenticated( + session: session, conditions: event.conditions)); } on UnauthorizedException catch (_) { emit(const AuthState.unauthenticated()); } on TwoFactorAuthRequiredException catch (_) { - emit(const AuthState.aal2Requested()); + emit(AuthState.aal2Requested(conditions: event.conditions)); } on UnknownException catch (e) { emit(state.copyWith(isLoading: false, errorMessage: e.message)); } catch (_) { diff --git a/flutter-ory-network/lib/blocs/auth/auth_bloc.freezed.dart b/flutter-ory-network/lib/blocs/auth/auth_bloc.freezed.dart index d9c8dbde..d028d539 100644 --- a/flutter-ory-network/lib/blocs/auth/auth_bloc.freezed.dart +++ b/flutter-ory-network/lib/blocs/auth/auth_bloc.freezed.dart @@ -20,56 +20,63 @@ final _privateConstructorUsedError = UnsupportedError( /// @nodoc mixin _$AuthState { AuthStatus get status => throw _privateConstructorUsedError; + List get conditions => throw _privateConstructorUsedError; bool get isLoading => throw _privateConstructorUsedError; String? get errorMessage => throw _privateConstructorUsedError; @optionalTypeArgs TResult when({ - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) uninitialized, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) unauthenticated, required TResult Function(AuthStatus status, Session session, - bool isLoading, String? errorMessage) + List conditions, bool isLoading, String? errorMessage) authenticated, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) aal2Requested, - required TResult Function( - AuthStatus status, String url, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + String url, bool isLoading, String? errorMessage) locationChangeRequired, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult? Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult? Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, required TResult orElse(), }) => @@ -114,7 +121,11 @@ abstract class $AuthStateCopyWith<$Res> { factory $AuthStateCopyWith(AuthState value, $Res Function(AuthState) then) = _$AuthStateCopyWithImpl<$Res, AuthState>; @useResult - $Res call({AuthStatus status, bool isLoading, String? errorMessage}); + $Res call( + {AuthStatus status, + List conditions, + bool isLoading, + String? errorMessage}); } /// @nodoc @@ -131,6 +142,7 @@ class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState> @override $Res call({ Object? status = null, + Object? conditions = null, Object? isLoading = null, Object? errorMessage = freezed, }) { @@ -139,6 +151,10 @@ class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState> ? _value.status : status // ignore: cast_nullable_to_non_nullable as AuthStatus, + conditions: null == conditions + ? _value.conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, isLoading: null == isLoading ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable @@ -159,7 +175,11 @@ abstract class _$$AuthUninitializedImplCopyWith<$Res> __$$AuthUninitializedImplCopyWithImpl<$Res>; @override @useResult - $Res call({AuthStatus status, bool isLoading, String? errorMessage}); + $Res call( + {AuthStatus status, + List conditions, + bool isLoading, + String? errorMessage}); } /// @nodoc @@ -174,6 +194,7 @@ class __$$AuthUninitializedImplCopyWithImpl<$Res> @override $Res call({ Object? status = null, + Object? conditions = null, Object? isLoading = null, Object? errorMessage = freezed, }) { @@ -182,6 +203,10 @@ class __$$AuthUninitializedImplCopyWithImpl<$Res> ? _value.status : status // ignore: cast_nullable_to_non_nullable as AuthStatus, + conditions: null == conditions + ? _value._conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, isLoading: null == isLoading ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable @@ -199,12 +224,23 @@ class __$$AuthUninitializedImplCopyWithImpl<$Res> class _$AuthUninitializedImpl implements AuthUninitialized { const _$AuthUninitializedImpl( {this.status = AuthStatus.uninitialized, + final List conditions = const [], this.isLoading = false, - this.errorMessage}); + this.errorMessage}) + : _conditions = conditions; @override @JsonKey() final AuthStatus status; + final List _conditions; + @override + @JsonKey() + List get conditions { + if (_conditions is EqualUnmodifiableListView) return _conditions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_conditions); + } + @override @JsonKey() final bool isLoading; @@ -213,7 +249,7 @@ class _$AuthUninitializedImpl implements AuthUninitialized { @override String toString() { - return 'AuthState.uninitialized(status: $status, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'AuthState.uninitialized(status: $status, conditions: $conditions, isLoading: $isLoading, errorMessage: $errorMessage)'; } @override @@ -222,6 +258,8 @@ class _$AuthUninitializedImpl implements AuthUninitialized { (other.runtimeType == runtimeType && other is _$AuthUninitializedImpl && (identical(other.status, status) || other.status == status) && + const DeepCollectionEquality() + .equals(other._conditions, _conditions) && (identical(other.isLoading, isLoading) || other.isLoading == isLoading) && (identical(other.errorMessage, errorMessage) || @@ -229,7 +267,12 @@ class _$AuthUninitializedImpl implements AuthUninitialized { } @override - int get hashCode => Object.hash(runtimeType, status, isLoading, errorMessage); + int get hashCode => Object.hash( + runtimeType, + status, + const DeepCollectionEquality().hash(_conditions), + isLoading, + errorMessage); @JsonKey(ignore: true) @override @@ -241,63 +284,69 @@ class _$AuthUninitializedImpl implements AuthUninitialized { @override @optionalTypeArgs TResult when({ - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) uninitialized, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) unauthenticated, required TResult Function(AuthStatus status, Session session, - bool isLoading, String? errorMessage) + List conditions, bool isLoading, String? errorMessage) authenticated, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) aal2Requested, - required TResult Function( - AuthStatus status, String url, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + String url, bool isLoading, String? errorMessage) locationChangeRequired, }) { - return uninitialized(status, isLoading, errorMessage); + return uninitialized(status, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult? Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult? Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, }) { - return uninitialized?.call(status, isLoading, errorMessage); + return uninitialized?.call(status, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, required TResult orElse(), }) { if (uninitialized != null) { - return uninitialized(status, isLoading, errorMessage); + return uninitialized(status, conditions, isLoading, errorMessage); } return orElse(); } @@ -347,12 +396,15 @@ class _$AuthUninitializedImpl implements AuthUninitialized { abstract class AuthUninitialized implements AuthState { const factory AuthUninitialized( {final AuthStatus status, + final List conditions, final bool isLoading, final String? errorMessage}) = _$AuthUninitializedImpl; @override AuthStatus get status; @override + List get conditions; + @override bool get isLoading; @override String? get errorMessage; @@ -370,7 +422,11 @@ abstract class _$$AuthUnauthenticatedImplCopyWith<$Res> __$$AuthUnauthenticatedImplCopyWithImpl<$Res>; @override @useResult - $Res call({AuthStatus status, bool isLoading, String? errorMessage}); + $Res call( + {AuthStatus status, + List conditions, + bool isLoading, + String? errorMessage}); } /// @nodoc @@ -385,6 +441,7 @@ class __$$AuthUnauthenticatedImplCopyWithImpl<$Res> @override $Res call({ Object? status = null, + Object? conditions = null, Object? isLoading = null, Object? errorMessage = freezed, }) { @@ -393,6 +450,10 @@ class __$$AuthUnauthenticatedImplCopyWithImpl<$Res> ? _value.status : status // ignore: cast_nullable_to_non_nullable as AuthStatus, + conditions: null == conditions + ? _value._conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, isLoading: null == isLoading ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable @@ -410,12 +471,23 @@ class __$$AuthUnauthenticatedImplCopyWithImpl<$Res> class _$AuthUnauthenticatedImpl implements AuthUnauthenticated { const _$AuthUnauthenticatedImpl( {this.status = AuthStatus.unauthenticated, + final List conditions = const [], this.isLoading = false, - this.errorMessage}); + this.errorMessage}) + : _conditions = conditions; @override @JsonKey() final AuthStatus status; + final List _conditions; + @override + @JsonKey() + List get conditions { + if (_conditions is EqualUnmodifiableListView) return _conditions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_conditions); + } + @override @JsonKey() final bool isLoading; @@ -424,7 +496,7 @@ class _$AuthUnauthenticatedImpl implements AuthUnauthenticated { @override String toString() { - return 'AuthState.unauthenticated(status: $status, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'AuthState.unauthenticated(status: $status, conditions: $conditions, isLoading: $isLoading, errorMessage: $errorMessage)'; } @override @@ -433,6 +505,8 @@ class _$AuthUnauthenticatedImpl implements AuthUnauthenticated { (other.runtimeType == runtimeType && other is _$AuthUnauthenticatedImpl && (identical(other.status, status) || other.status == status) && + const DeepCollectionEquality() + .equals(other._conditions, _conditions) && (identical(other.isLoading, isLoading) || other.isLoading == isLoading) && (identical(other.errorMessage, errorMessage) || @@ -440,7 +514,12 @@ class _$AuthUnauthenticatedImpl implements AuthUnauthenticated { } @override - int get hashCode => Object.hash(runtimeType, status, isLoading, errorMessage); + int get hashCode => Object.hash( + runtimeType, + status, + const DeepCollectionEquality().hash(_conditions), + isLoading, + errorMessage); @JsonKey(ignore: true) @override @@ -452,63 +531,69 @@ class _$AuthUnauthenticatedImpl implements AuthUnauthenticated { @override @optionalTypeArgs TResult when({ - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) uninitialized, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) unauthenticated, required TResult Function(AuthStatus status, Session session, - bool isLoading, String? errorMessage) + List conditions, bool isLoading, String? errorMessage) authenticated, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) aal2Requested, - required TResult Function( - AuthStatus status, String url, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + String url, bool isLoading, String? errorMessage) locationChangeRequired, }) { - return unauthenticated(status, isLoading, errorMessage); + return unauthenticated(status, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult? Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult? Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, }) { - return unauthenticated?.call(status, isLoading, errorMessage); + return unauthenticated?.call(status, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, required TResult orElse(), }) { if (unauthenticated != null) { - return unauthenticated(status, isLoading, errorMessage); + return unauthenticated(status, conditions, isLoading, errorMessage); } return orElse(); } @@ -558,12 +643,15 @@ class _$AuthUnauthenticatedImpl implements AuthUnauthenticated { abstract class AuthUnauthenticated implements AuthState { const factory AuthUnauthenticated( {final AuthStatus status, + final List conditions, final bool isLoading, final String? errorMessage}) = _$AuthUnauthenticatedImpl; @override AuthStatus get status; @override + List get conditions; + @override bool get isLoading; @override String? get errorMessage; @@ -584,6 +672,7 @@ abstract class _$$AuthAuthenticatedImplCopyWith<$Res> $Res call( {AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage}); } @@ -601,6 +690,7 @@ class __$$AuthAuthenticatedImplCopyWithImpl<$Res> $Res call({ Object? status = null, Object? session = null, + Object? conditions = null, Object? isLoading = null, Object? errorMessage = freezed, }) { @@ -613,6 +703,10 @@ class __$$AuthAuthenticatedImplCopyWithImpl<$Res> ? _value.session : session // ignore: cast_nullable_to_non_nullable as Session, + conditions: null == conditions + ? _value._conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, isLoading: null == isLoading ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable @@ -631,14 +725,25 @@ class _$AuthAuthenticatedImpl implements AuthAuthenticated { const _$AuthAuthenticatedImpl( {this.status = AuthStatus.authenticated, required this.session, + final List conditions = const [], this.isLoading = false, - this.errorMessage}); + this.errorMessage}) + : _conditions = conditions; @override @JsonKey() final AuthStatus status; @override final Session session; + final List _conditions; + @override + @JsonKey() + List get conditions { + if (_conditions is EqualUnmodifiableListView) return _conditions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_conditions); + } + @override @JsonKey() final bool isLoading; @@ -647,7 +752,7 @@ class _$AuthAuthenticatedImpl implements AuthAuthenticated { @override String toString() { - return 'AuthState.authenticated(status: $status, session: $session, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'AuthState.authenticated(status: $status, session: $session, conditions: $conditions, isLoading: $isLoading, errorMessage: $errorMessage)'; } @override @@ -657,6 +762,8 @@ class _$AuthAuthenticatedImpl implements AuthAuthenticated { other is _$AuthAuthenticatedImpl && (identical(other.status, status) || other.status == status) && (identical(other.session, session) || other.session == session) && + const DeepCollectionEquality() + .equals(other._conditions, _conditions) && (identical(other.isLoading, isLoading) || other.isLoading == isLoading) && (identical(other.errorMessage, errorMessage) || @@ -664,8 +771,13 @@ class _$AuthAuthenticatedImpl implements AuthAuthenticated { } @override - int get hashCode => - Object.hash(runtimeType, status, session, isLoading, errorMessage); + int get hashCode => Object.hash( + runtimeType, + status, + session, + const DeepCollectionEquality().hash(_conditions), + isLoading, + errorMessage); @JsonKey(ignore: true) @override @@ -677,63 +789,71 @@ class _$AuthAuthenticatedImpl implements AuthAuthenticated { @override @optionalTypeArgs TResult when({ - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) uninitialized, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) unauthenticated, required TResult Function(AuthStatus status, Session session, - bool isLoading, String? errorMessage) + List conditions, bool isLoading, String? errorMessage) authenticated, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) aal2Requested, - required TResult Function( - AuthStatus status, String url, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + String url, bool isLoading, String? errorMessage) locationChangeRequired, }) { - return authenticated(status, session, isLoading, errorMessage); + return authenticated(status, session, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult? Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult? Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, }) { - return authenticated?.call(status, session, isLoading, errorMessage); + return authenticated?.call( + status, session, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, required TResult orElse(), }) { if (authenticated != null) { - return authenticated(status, session, isLoading, errorMessage); + return authenticated( + status, session, conditions, isLoading, errorMessage); } return orElse(); } @@ -784,6 +904,7 @@ abstract class AuthAuthenticated implements AuthState { const factory AuthAuthenticated( {final AuthStatus status, required final Session session, + final List conditions, final bool isLoading, final String? errorMessage}) = _$AuthAuthenticatedImpl; @@ -791,6 +912,8 @@ abstract class AuthAuthenticated implements AuthState { AuthStatus get status; Session get session; @override + List get conditions; + @override bool get isLoading; @override String? get errorMessage; @@ -808,7 +931,11 @@ abstract class _$$Aal2RequestedImplCopyWith<$Res> __$$Aal2RequestedImplCopyWithImpl<$Res>; @override @useResult - $Res call({AuthStatus status, bool isLoading, String? errorMessage}); + $Res call( + {AuthStatus status, + List conditions, + bool isLoading, + String? errorMessage}); } /// @nodoc @@ -823,6 +950,7 @@ class __$$Aal2RequestedImplCopyWithImpl<$Res> @override $Res call({ Object? status = null, + Object? conditions = null, Object? isLoading = null, Object? errorMessage = freezed, }) { @@ -831,6 +959,10 @@ class __$$Aal2RequestedImplCopyWithImpl<$Res> ? _value.status : status // ignore: cast_nullable_to_non_nullable as AuthStatus, + conditions: null == conditions + ? _value._conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, isLoading: null == isLoading ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable @@ -848,12 +980,23 @@ class __$$Aal2RequestedImplCopyWithImpl<$Res> class _$Aal2RequestedImpl implements Aal2Requested { const _$Aal2RequestedImpl( {this.status = AuthStatus.aal2Requested, + final List conditions = const [], this.isLoading = false, - this.errorMessage}); + this.errorMessage}) + : _conditions = conditions; @override @JsonKey() final AuthStatus status; + final List _conditions; + @override + @JsonKey() + List get conditions { + if (_conditions is EqualUnmodifiableListView) return _conditions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_conditions); + } + @override @JsonKey() final bool isLoading; @@ -862,7 +1005,7 @@ class _$Aal2RequestedImpl implements Aal2Requested { @override String toString() { - return 'AuthState.aal2Requested(status: $status, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'AuthState.aal2Requested(status: $status, conditions: $conditions, isLoading: $isLoading, errorMessage: $errorMessage)'; } @override @@ -871,6 +1014,8 @@ class _$Aal2RequestedImpl implements Aal2Requested { (other.runtimeType == runtimeType && other is _$Aal2RequestedImpl && (identical(other.status, status) || other.status == status) && + const DeepCollectionEquality() + .equals(other._conditions, _conditions) && (identical(other.isLoading, isLoading) || other.isLoading == isLoading) && (identical(other.errorMessage, errorMessage) || @@ -878,7 +1023,12 @@ class _$Aal2RequestedImpl implements Aal2Requested { } @override - int get hashCode => Object.hash(runtimeType, status, isLoading, errorMessage); + int get hashCode => Object.hash( + runtimeType, + status, + const DeepCollectionEquality().hash(_conditions), + isLoading, + errorMessage); @JsonKey(ignore: true) @override @@ -889,63 +1039,69 @@ class _$Aal2RequestedImpl implements Aal2Requested { @override @optionalTypeArgs TResult when({ - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) uninitialized, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) unauthenticated, required TResult Function(AuthStatus status, Session session, - bool isLoading, String? errorMessage) + List conditions, bool isLoading, String? errorMessage) authenticated, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) aal2Requested, - required TResult Function( - AuthStatus status, String url, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + String url, bool isLoading, String? errorMessage) locationChangeRequired, }) { - return aal2Requested(status, isLoading, errorMessage); + return aal2Requested(status, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult? Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult? Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, }) { - return aal2Requested?.call(status, isLoading, errorMessage); + return aal2Requested?.call(status, conditions, isLoading, errorMessage); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, required TResult orElse(), }) { if (aal2Requested != null) { - return aal2Requested(status, isLoading, errorMessage); + return aal2Requested(status, conditions, isLoading, errorMessage); } return orElse(); } @@ -995,12 +1151,15 @@ class _$Aal2RequestedImpl implements Aal2Requested { abstract class Aal2Requested implements AuthState { const factory Aal2Requested( {final AuthStatus status, + final List conditions, final bool isLoading, final String? errorMessage}) = _$Aal2RequestedImpl; @override AuthStatus get status; @override + List get conditions; + @override bool get isLoading; @override String? get errorMessage; @@ -1020,7 +1179,11 @@ abstract class _$$LocationChangeRequiredImplCopyWith<$Res> @override @useResult $Res call( - {AuthStatus status, String url, bool isLoading, String? errorMessage}); + {AuthStatus status, + List conditions, + String url, + bool isLoading, + String? errorMessage}); } /// @nodoc @@ -1036,6 +1199,7 @@ class __$$LocationChangeRequiredImplCopyWithImpl<$Res> @override $Res call({ Object? status = null, + Object? conditions = null, Object? url = null, Object? isLoading = null, Object? errorMessage = freezed, @@ -1045,6 +1209,10 @@ class __$$LocationChangeRequiredImplCopyWithImpl<$Res> ? _value.status : status // ignore: cast_nullable_to_non_nullable as AuthStatus, + conditions: null == conditions + ? _value._conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, url: null == url ? _value.url : url // ignore: cast_nullable_to_non_nullable @@ -1066,13 +1234,24 @@ class __$$LocationChangeRequiredImplCopyWithImpl<$Res> class _$LocationChangeRequiredImpl implements LocationChangeRequired { const _$LocationChangeRequiredImpl( {this.status = AuthStatus.locationChangeRequired, + final List conditions = const [], required this.url, this.isLoading = false, - this.errorMessage}); + this.errorMessage}) + : _conditions = conditions; @override @JsonKey() final AuthStatus status; + final List _conditions; + @override + @JsonKey() + List get conditions { + if (_conditions is EqualUnmodifiableListView) return _conditions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_conditions); + } + @override final String url; @override @@ -1083,7 +1262,7 @@ class _$LocationChangeRequiredImpl implements LocationChangeRequired { @override String toString() { - return 'AuthState.locationChangeRequired(status: $status, url: $url, isLoading: $isLoading, errorMessage: $errorMessage)'; + return 'AuthState.locationChangeRequired(status: $status, conditions: $conditions, url: $url, isLoading: $isLoading, errorMessage: $errorMessage)'; } @override @@ -1092,6 +1271,8 @@ class _$LocationChangeRequiredImpl implements LocationChangeRequired { (other.runtimeType == runtimeType && other is _$LocationChangeRequiredImpl && (identical(other.status, status) || other.status == status) && + const DeepCollectionEquality() + .equals(other._conditions, _conditions) && (identical(other.url, url) || other.url == url) && (identical(other.isLoading, isLoading) || other.isLoading == isLoading) && @@ -1100,8 +1281,13 @@ class _$LocationChangeRequiredImpl implements LocationChangeRequired { } @override - int get hashCode => - Object.hash(runtimeType, status, url, isLoading, errorMessage); + int get hashCode => Object.hash( + runtimeType, + status, + const DeepCollectionEquality().hash(_conditions), + url, + isLoading, + errorMessage); @JsonKey(ignore: true) @override @@ -1113,63 +1299,72 @@ class _$LocationChangeRequiredImpl implements LocationChangeRequired { @override @optionalTypeArgs TResult when({ - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) uninitialized, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) unauthenticated, required TResult Function(AuthStatus status, Session session, - bool isLoading, String? errorMessage) + List conditions, bool isLoading, String? errorMessage) authenticated, - required TResult Function( - AuthStatus status, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage) aal2Requested, - required TResult Function( - AuthStatus status, String url, bool isLoading, String? errorMessage) + required TResult Function(AuthStatus status, List conditions, + String url, bool isLoading, String? errorMessage) locationChangeRequired, }) { - return locationChangeRequired(status, url, isLoading, errorMessage); + return locationChangeRequired( + status, conditions, url, isLoading, errorMessage); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult? Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult? Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult? Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult? Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, }) { - return locationChangeRequired?.call(status, url, isLoading, errorMessage); + return locationChangeRequired?.call( + status, conditions, url, isLoading, errorMessage); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? uninitialized, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? unauthenticated, - TResult Function(AuthStatus status, Session session, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, Session session, + List conditions, bool isLoading, String? errorMessage)? authenticated, - TResult Function(AuthStatus status, bool isLoading, String? errorMessage)? + TResult Function(AuthStatus status, List conditions, + bool isLoading, String? errorMessage)? aal2Requested, - TResult Function(AuthStatus status, String url, bool isLoading, - String? errorMessage)? + TResult Function(AuthStatus status, List conditions, String url, + bool isLoading, String? errorMessage)? locationChangeRequired, required TResult orElse(), }) { if (locationChangeRequired != null) { - return locationChangeRequired(status, url, isLoading, errorMessage); + return locationChangeRequired( + status, conditions, url, isLoading, errorMessage); } return orElse(); } @@ -1219,12 +1414,15 @@ class _$LocationChangeRequiredImpl implements LocationChangeRequired { abstract class LocationChangeRequired implements AuthState { const factory LocationChangeRequired( {final AuthStatus status, + final List conditions, required final String url, final bool isLoading, final String? errorMessage}) = _$LocationChangeRequiredImpl; @override AuthStatus get status; + @override + List get conditions; String get url; @override bool get isLoading; diff --git a/flutter-ory-network/lib/blocs/auth/auth_event.dart b/flutter-ory-network/lib/blocs/auth/auth_event.dart index 74f6c0a4..db7cf08d 100644 --- a/flutter-ory-network/lib/blocs/auth/auth_event.dart +++ b/flutter-ory-network/lib/blocs/auth/auth_event.dart @@ -11,14 +11,23 @@ sealed class AuthEvent extends Equatable { final class ChangeAuthStatus extends AuthEvent { final AuthStatus status; + final List conditions; final Session? session; - ChangeAuthStatus({required this.status, this.session}); + ChangeAuthStatus( + {required this.status, this.session, this.conditions = const []}); @override - List get props => [status, session]; + List get props => [status, session, conditions]; } -final class GetCurrentSessionInformation extends AuthEvent {} +final class GetCurrentSessionInformation extends AuthEvent { + final List conditions; + + GetCurrentSessionInformation({this.conditions = const []}); + + @override + List get props => [conditions]; +} final class RequireLocationChange extends AuthEvent { final String url; @@ -30,10 +39,11 @@ final class RequireLocationChange extends AuthEvent { final class AddSession extends AuthEvent { final Session session; + final List conditions; - AddSession({required this.session}); + AddSession({required this.session, this.conditions = const []}); @override - List get props => [session]; + List get props => [session, conditions]; } final class LogOut extends AuthEvent {} diff --git a/flutter-ory-network/lib/blocs/auth/auth_state.dart b/flutter-ory-network/lib/blocs/auth/auth_state.dart index 9462fbef..7ab8cabe 100644 --- a/flutter-ory-network/lib/blocs/auth/auth_state.dart +++ b/flutter-ory-network/lib/blocs/auth/auth_state.dart @@ -7,26 +7,40 @@ part of 'auth_bloc.dart'; sealed class AuthState with _$AuthState { const factory AuthState.uninitialized( {@Default(AuthStatus.uninitialized) final AuthStatus status, + @Default([]) List conditions, @Default(false) bool isLoading, String? errorMessage}) = AuthUninitialized; const factory AuthState.unauthenticated( {@Default(AuthStatus.unauthenticated) final AuthStatus status, + @Default([]) List conditions, @Default(false) bool isLoading, String? errorMessage}) = AuthUnauthenticated; const factory AuthState.authenticated( {@Default(AuthStatus.authenticated) final AuthStatus status, required Session session, + @Default([]) List conditions, @Default(false) bool isLoading, String? errorMessage}) = AuthAuthenticated; - const factory AuthState.aal2Requested( {@Default(AuthStatus.aal2Requested) final AuthStatus status, + @Default([]) List conditions, @Default(false) bool isLoading, String? errorMessage}) = Aal2Requested; const factory AuthState.locationChangeRequired( {@Default(AuthStatus.locationChangeRequired) final AuthStatus status, + @Default([]) List conditions, required String url, @Default(false) bool isLoading, String? errorMessage}) = LocationChangeRequired; } + +class Condition {} + +class RecoveryRequested extends Condition { + final String settingsFlowId; + + RecoveryRequested({required this.settingsFlowId}); +} + +class SessionRefreshRequested extends Condition {} diff --git a/flutter-ory-network/lib/blocs/bloc/recovery_bloc.dart b/flutter-ory-network/lib/blocs/bloc/recovery_bloc.dart new file mode 100644 index 00000000..aa1a5444 --- /dev/null +++ b/flutter-ory-network/lib/blocs/bloc/recovery_bloc.dart @@ -0,0 +1,67 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:ory_client/ory_client.dart'; +import 'package:ory_network_flutter/repositories/auth.dart'; + +import '../../services/exceptions.dart'; + +part 'recovery_event.dart'; +part 'recovery_state.dart'; +part 'recovery_bloc.freezed.dart'; + +class RecoveryBloc extends Bloc { + final AuthRepository repository; + RecoveryBloc({required this.repository}) : super(const RecoveryState()) { + on(_onCreateRecoveryFlow); + on(_onChangeNodeValue); + // on(_onGetRecoveryFlow); + on(_onUpdateRecoveryFlow); + } + + Future _onCreateRecoveryFlow( + CreateRecoveryFlow event, Emitter emit) async { + try { + emit(state.copyWith(isLoading: true, message: null)); + + final recoveryFlow = await repository.createRecoveryFlow(); + + emit(state.copyWith(recoveryFlow: recoveryFlow, isLoading: false)); + } on UnknownException catch (e) { + emit(state.copyWith(isLoading: false, message: e.message)); + } catch (_) { + emit(state.copyWith(isLoading: false)); + } + } + + _onChangeNodeValue(ChangeNodeValue event, Emitter emit) { + if (state.recoveryFlow != null) { + final newRecoveryState = repository.changeRecoveryNodeValue( + flow: state.recoveryFlow!, name: event.name, value: event.value); + emit(state.copyWith(recoveryFlow: newRecoveryState, message: null)); + } + } + + Future _onUpdateRecoveryFlow( + UpdateRecoveryFlow event, Emitter emit) async { + try { + if (state.recoveryFlow != null) { + emit(state.copyWith(isLoading: true, message: null)); + final recoveryFlow = await repository.updateRecoveryFlow( + flowId: state.recoveryFlow!.id, + group: event.group, + name: event.name, + value: event.value, + nodes: state.recoveryFlow!.ui.nodes.toList()); + emit(state.copyWith(recoveryFlow: recoveryFlow, isLoading: false)); + } + } on BadRequestException catch (e) { + emit(state.copyWith(recoveryFlow: e.flow, isLoading: false)); + } on settingsRedirectRequired catch (e) { + emit(state.copyWith(settingsFlowId: e.settingsFlowId)); + } + } +} diff --git a/flutter-ory-network/lib/blocs/bloc/recovery_bloc.freezed.dart b/flutter-ory-network/lib/blocs/bloc/recovery_bloc.freezed.dart new file mode 100644 index 00000000..f09b26ad --- /dev/null +++ b/flutter-ory-network/lib/blocs/bloc/recovery_bloc.freezed.dart @@ -0,0 +1,200 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'recovery_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +/// @nodoc +mixin _$RecoveryState { + RecoveryFlow? get recoveryFlow => throw _privateConstructorUsedError; + dynamic get isLoading => throw _privateConstructorUsedError; + String? get settingsFlowId => throw _privateConstructorUsedError; + String? get message => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $RecoveryStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $RecoveryStateCopyWith<$Res> { + factory $RecoveryStateCopyWith( + RecoveryState value, $Res Function(RecoveryState) then) = + _$RecoveryStateCopyWithImpl<$Res, RecoveryState>; + @useResult + $Res call( + {RecoveryFlow? recoveryFlow, + dynamic isLoading, + String? settingsFlowId, + String? message}); +} + +/// @nodoc +class _$RecoveryStateCopyWithImpl<$Res, $Val extends RecoveryState> + implements $RecoveryStateCopyWith<$Res> { + _$RecoveryStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? recoveryFlow = freezed, + Object? isLoading = freezed, + Object? settingsFlowId = freezed, + Object? message = freezed, + }) { + return _then(_value.copyWith( + recoveryFlow: freezed == recoveryFlow + ? _value.recoveryFlow + : recoveryFlow // ignore: cast_nullable_to_non_nullable + as RecoveryFlow?, + isLoading: freezed == isLoading + ? _value.isLoading + : isLoading // ignore: cast_nullable_to_non_nullable + as dynamic, + settingsFlowId: freezed == settingsFlowId + ? _value.settingsFlowId + : settingsFlowId // ignore: cast_nullable_to_non_nullable + as String?, + message: freezed == message + ? _value.message + : message // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$RecoveryStateImplCopyWith<$Res> + implements $RecoveryStateCopyWith<$Res> { + factory _$$RecoveryStateImplCopyWith( + _$RecoveryStateImpl value, $Res Function(_$RecoveryStateImpl) then) = + __$$RecoveryStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {RecoveryFlow? recoveryFlow, + dynamic isLoading, + String? settingsFlowId, + String? message}); +} + +/// @nodoc +class __$$RecoveryStateImplCopyWithImpl<$Res> + extends _$RecoveryStateCopyWithImpl<$Res, _$RecoveryStateImpl> + implements _$$RecoveryStateImplCopyWith<$Res> { + __$$RecoveryStateImplCopyWithImpl( + _$RecoveryStateImpl _value, $Res Function(_$RecoveryStateImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? recoveryFlow = freezed, + Object? isLoading = freezed, + Object? settingsFlowId = freezed, + Object? message = freezed, + }) { + return _then(_$RecoveryStateImpl( + recoveryFlow: freezed == recoveryFlow + ? _value.recoveryFlow + : recoveryFlow // ignore: cast_nullable_to_non_nullable + as RecoveryFlow?, + isLoading: freezed == isLoading ? _value.isLoading! : isLoading, + settingsFlowId: freezed == settingsFlowId + ? _value.settingsFlowId + : settingsFlowId // ignore: cast_nullable_to_non_nullable + as String?, + message: freezed == message + ? _value.message + : message // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc + +class _$RecoveryStateImpl implements _RecoveryState { + const _$RecoveryStateImpl( + {this.recoveryFlow, + this.isLoading = false, + this.settingsFlowId, + this.message}); + + @override + final RecoveryFlow? recoveryFlow; + @override + @JsonKey() + final dynamic isLoading; + @override + final String? settingsFlowId; + @override + final String? message; + + @override + String toString() { + return 'RecoveryState(recoveryFlow: $recoveryFlow, isLoading: $isLoading, settingsFlowId: $settingsFlowId, message: $message)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$RecoveryStateImpl && + (identical(other.recoveryFlow, recoveryFlow) || + other.recoveryFlow == recoveryFlow) && + const DeepCollectionEquality().equals(other.isLoading, isLoading) && + (identical(other.settingsFlowId, settingsFlowId) || + other.settingsFlowId == settingsFlowId) && + (identical(other.message, message) || other.message == message)); + } + + @override + int get hashCode => Object.hash(runtimeType, recoveryFlow, + const DeepCollectionEquality().hash(isLoading), settingsFlowId, message); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$RecoveryStateImplCopyWith<_$RecoveryStateImpl> get copyWith => + __$$RecoveryStateImplCopyWithImpl<_$RecoveryStateImpl>(this, _$identity); +} + +abstract class _RecoveryState implements RecoveryState { + const factory _RecoveryState( + {final RecoveryFlow? recoveryFlow, + final dynamic isLoading, + final String? settingsFlowId, + final String? message}) = _$RecoveryStateImpl; + + @override + RecoveryFlow? get recoveryFlow; + @override + dynamic get isLoading; + @override + String? get settingsFlowId; + @override + String? get message; + @override + @JsonKey(ignore: true) + _$$RecoveryStateImplCopyWith<_$RecoveryStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/flutter-ory-network/lib/blocs/bloc/recovery_event.dart b/flutter-ory-network/lib/blocs/bloc/recovery_event.dart new file mode 100644 index 00000000..572d1715 --- /dev/null +++ b/flutter-ory-network/lib/blocs/bloc/recovery_event.dart @@ -0,0 +1,39 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +part of 'recovery_bloc.dart'; + +@immutable +sealed class RecoveryEvent extends Equatable { + @override + List get props => []; +} + +class CreateRecoveryFlow extends RecoveryEvent {} + +class GetRecoveryFlow extends RecoveryEvent { + final String flowId; + GetRecoveryFlow({required this.flowId}); + @override + List get props => [flowId]; +} + +class UpdateRecoveryFlow extends RecoveryEvent { + final UiNodeGroupEnum group; + final String name; + final String value; + + UpdateRecoveryFlow( + {required this.group, required this.name, required this.value}); + @override + List get props => [group, name, value]; +} + +class ChangeNodeValue extends RecoveryEvent { + final String value; + final String name; + + ChangeNodeValue({required this.value, required this.name}); + @override + List get props => [value, name]; +} diff --git a/flutter-ory-network/lib/blocs/bloc/recovery_state.dart b/flutter-ory-network/lib/blocs/bloc/recovery_state.dart new file mode 100644 index 00000000..bdf17b66 --- /dev/null +++ b/flutter-ory-network/lib/blocs/bloc/recovery_state.dart @@ -0,0 +1,13 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +part of 'recovery_bloc.dart'; + +@freezed +sealed class RecoveryState with _$RecoveryState { + const factory RecoveryState( + {RecoveryFlow? recoveryFlow, + @Default(false) isLoading, + String? settingsFlowId, + String? message}) = _RecoveryState; +} diff --git a/flutter-ory-network/lib/blocs/login/login_bloc.dart b/flutter-ory-network/lib/blocs/login/login_bloc.dart index 8ceead1e..a97b378d 100644 --- a/flutter-ory-network/lib/blocs/login/login_bloc.dart +++ b/flutter-ory-network/lib/blocs/login/login_bloc.dart @@ -2,9 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 import 'package:bloc/bloc.dart'; +import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:ory_client/ory_client.dart'; +import 'package:ory_network_flutter/widgets/helpers.dart'; import '../../repositories/auth.dart'; import '../../services/exceptions.dart'; @@ -17,8 +19,13 @@ part 'login_bloc.freezed.dart'; class LoginBloc extends Bloc { final AuthBloc authBloc; final AuthRepository repository; - LoginBloc({required this.authBloc, required this.repository}) - : super(const LoginState()) { + final List conditions; + + LoginBloc( + {required this.authBloc, + required this.repository, + this.conditions = const []}) + : super(LoginState(conditions: conditions)) { on(_onCreateLoginFlow); on(_onGetLoginFlow); on(_onExchangesCodeForSessionToken); @@ -31,8 +38,9 @@ class LoginBloc extends Bloc { CreateLoginFlow event, Emitter emit) async { try { emit(state.copyWith(isLoading: true, message: null)); - final loginFlow = await repository.createLoginFlow( - aal: event.aal, refresh: event.refresh); + final refresh = isSessionRefreshRequired(state.conditions); + final loginFlow = + await repository.createLoginFlow(aal: event.aal, refresh: refresh); emit(state.copyWith(loginFlow: loginFlow, isLoading: false)); } on UnknownException catch (e) { emit(state.copyWith(isLoading: false, message: e.message)); @@ -86,7 +94,7 @@ class LoginBloc extends Bloc { _onChangeNodeValue(ChangeNodeValue event, Emitter emit) { if (state.loginFlow != null) { final newLoginState = repository.changeLoginNodeValue( - settings: state.loginFlow!, name: event.name, value: event.value); + flow: state.loginFlow!, name: event.name, value: event.value); emit(state.copyWith(loginFlow: newLoginState, message: null)); } } @@ -100,7 +108,8 @@ class LoginBloc extends Bloc { name: event.name, value: event.value, nodes: state.loginFlow!.ui.nodes.toList()); - authBloc.add(AddSession(session: session)); + + authBloc.add(AddSession(session: session, conditions: state.conditions)); emit(state.copyWith(isLoading: false)); } on BadRequestException catch (e) { emit(state.copyWith(loginFlow: e.flow, isLoading: false)); @@ -112,7 +121,8 @@ class LoginBloc extends Bloc { } on FlowExpiredException catch (e) { add(GetLoginFlow(flowId: e.flowId)); } on TwoFactorAuthRequiredException catch (_) { - authBloc.add(ChangeAuthStatus(status: AuthStatus.aal2Requested)); + authBloc.add(ChangeAuthStatus( + status: AuthStatus.aal2Requested, conditions: state.conditions)); } on UnknownException catch (e) { emit(state.copyWith(isLoading: false, message: e.message)); } catch (_) { diff --git a/flutter-ory-network/lib/blocs/login/login_bloc.freezed.dart b/flutter-ory-network/lib/blocs/login/login_bloc.freezed.dart index 52bd2120..cb83c3a1 100644 --- a/flutter-ory-network/lib/blocs/login/login_bloc.freezed.dart +++ b/flutter-ory-network/lib/blocs/login/login_bloc.freezed.dart @@ -20,6 +20,7 @@ final _privateConstructorUsedError = UnsupportedError( /// @nodoc mixin _$LoginState { LoginFlow? get loginFlow => throw _privateConstructorUsedError; + List get conditions => throw _privateConstructorUsedError; bool get isLoading => throw _privateConstructorUsedError; String? get message => throw _privateConstructorUsedError; @@ -34,7 +35,11 @@ abstract class $LoginStateCopyWith<$Res> { LoginState value, $Res Function(LoginState) then) = _$LoginStateCopyWithImpl<$Res, LoginState>; @useResult - $Res call({LoginFlow? loginFlow, bool isLoading, String? message}); + $Res call( + {LoginFlow? loginFlow, + List conditions, + bool isLoading, + String? message}); } /// @nodoc @@ -51,6 +56,7 @@ class _$LoginStateCopyWithImpl<$Res, $Val extends LoginState> @override $Res call({ Object? loginFlow = freezed, + Object? conditions = null, Object? isLoading = null, Object? message = freezed, }) { @@ -59,6 +65,10 @@ class _$LoginStateCopyWithImpl<$Res, $Val extends LoginState> ? _value.loginFlow : loginFlow // ignore: cast_nullable_to_non_nullable as LoginFlow?, + conditions: null == conditions + ? _value.conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, isLoading: null == isLoading ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable @@ -79,7 +89,11 @@ abstract class _$$LoginStateImplCopyWith<$Res> __$$LoginStateImplCopyWithImpl<$Res>; @override @useResult - $Res call({LoginFlow? loginFlow, bool isLoading, String? message}); + $Res call( + {LoginFlow? loginFlow, + List conditions, + bool isLoading, + String? message}); } /// @nodoc @@ -94,6 +108,7 @@ class __$$LoginStateImplCopyWithImpl<$Res> @override $Res call({ Object? loginFlow = freezed, + Object? conditions = null, Object? isLoading = null, Object? message = freezed, }) { @@ -102,6 +117,10 @@ class __$$LoginStateImplCopyWithImpl<$Res> ? _value.loginFlow : loginFlow // ignore: cast_nullable_to_non_nullable as LoginFlow?, + conditions: null == conditions + ? _value._conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, isLoading: null == isLoading ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable @@ -118,10 +137,23 @@ class __$$LoginStateImplCopyWithImpl<$Res> class _$LoginStateImpl implements _LoginState { const _$LoginStateImpl( - {this.loginFlow, this.isLoading = false, this.message}); + {this.loginFlow, + final List conditions = const [], + this.isLoading = false, + this.message}) + : _conditions = conditions; @override final LoginFlow? loginFlow; + final List _conditions; + @override + @JsonKey() + List get conditions { + if (_conditions is EqualUnmodifiableListView) return _conditions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_conditions); + } + @override @JsonKey() final bool isLoading; @@ -130,7 +162,7 @@ class _$LoginStateImpl implements _LoginState { @override String toString() { - return 'LoginState(loginFlow: $loginFlow, isLoading: $isLoading, message: $message)'; + return 'LoginState(loginFlow: $loginFlow, conditions: $conditions, isLoading: $isLoading, message: $message)'; } @override @@ -140,13 +172,16 @@ class _$LoginStateImpl implements _LoginState { other is _$LoginStateImpl && (identical(other.loginFlow, loginFlow) || other.loginFlow == loginFlow) && + const DeepCollectionEquality() + .equals(other._conditions, _conditions) && (identical(other.isLoading, isLoading) || other.isLoading == isLoading) && (identical(other.message, message) || other.message == message)); } @override - int get hashCode => Object.hash(runtimeType, loginFlow, isLoading, message); + int get hashCode => Object.hash(runtimeType, loginFlow, + const DeepCollectionEquality().hash(_conditions), isLoading, message); @JsonKey(ignore: true) @override @@ -158,12 +193,15 @@ class _$LoginStateImpl implements _LoginState { abstract class _LoginState implements LoginState { const factory _LoginState( {final LoginFlow? loginFlow, + final List conditions, final bool isLoading, final String? message}) = _$LoginStateImpl; @override LoginFlow? get loginFlow; @override + List get conditions; + @override bool get isLoading; @override String? get message; diff --git a/flutter-ory-network/lib/blocs/login/login_event.dart b/flutter-ory-network/lib/blocs/login/login_event.dart index 18ac7386..24e6d752 100644 --- a/flutter-ory-network/lib/blocs/login/login_event.dart +++ b/flutter-ory-network/lib/blocs/login/login_event.dart @@ -55,9 +55,13 @@ class UpdateLoginFlow extends LoginEvent { final UiNodeGroupEnum group; final String name; final String value; + final bool recoveryRequested; UpdateLoginFlow( - {required this.group, required this.name, required this.value}); + {required this.group, + required this.name, + required this.value, + this.recoveryRequested = false}); @override - List get props => [group, name, value]; + List get props => [group, name, value, recoveryRequested]; } diff --git a/flutter-ory-network/lib/blocs/login/login_state.dart b/flutter-ory-network/lib/blocs/login/login_state.dart index f28cce9b..04e06d01 100644 --- a/flutter-ory-network/lib/blocs/login/login_state.dart +++ b/flutter-ory-network/lib/blocs/login/login_state.dart @@ -7,6 +7,7 @@ part of 'login_bloc.dart'; sealed class LoginState with _$LoginState { const factory LoginState( {LoginFlow? loginFlow, + @Default([]) List conditions, @Default(false) bool isLoading, String? message}) = _LoginState; } diff --git a/flutter-ory-network/lib/blocs/registration/registration_bloc.dart b/flutter-ory-network/lib/blocs/registration/registration_bloc.dart index 6d37bc73..1abed2ca 100644 --- a/flutter-ory-network/lib/blocs/registration/registration_bloc.dart +++ b/flutter-ory-network/lib/blocs/registration/registration_bloc.dart @@ -56,9 +56,7 @@ class RegistrationBloc extends Bloc { _onChangeNodeValue(ChangeNodeValue event, Emitter emit) { if (state.registrationFlow != null) { final newRegistrationState = repository.changeRegistrationNodeValue( - settings: state.registrationFlow!, - name: event.name, - value: event.value); + flow: state.registrationFlow!, name: event.name, value: event.value); emit(state.copyWith( registrationFlow: newRegistrationState, message: null)); } diff --git a/flutter-ory-network/lib/blocs/settings/settings_bloc.dart b/flutter-ory-network/lib/blocs/settings/settings_bloc.dart index 345d47a6..7cbc7bf7 100644 --- a/flutter-ory-network/lib/blocs/settings/settings_bloc.dart +++ b/flutter-ory-network/lib/blocs/settings/settings_bloc.dart @@ -52,14 +52,29 @@ class SettingsBloc extends Bloc { } _onResetSettings(ResetSettings event, Emitter emit) async { - if (state.settingsFlow != null) { - emit(state.copyWith(isLoading: true)); - final settings = - await repository.getSettingsFlow(flowId: state.settingsFlow!.id); - emit(state.copyWith( - settingsFlow: settings, - isSessionRefreshRequired: false, - isLoading: false)); + try { + if (state.settingsFlow != null) { + emit(state.copyWith(isLoading: true)); + final settings = + await repository.getSettingsFlow(flowId: state.settingsFlow!.id); + List updatedConditions = List.from(state.conditions); + updatedConditions + .removeWhere((element) => element is SessionRefreshRequested); + emit(state.copyWith( + settingsFlow: settings, + conditions: updatedConditions, + isLoading: false)); + } + } on UnauthorizedException catch (_) { + // change auth status as the user is not authenticated + authBloc.add(ChangeAuthStatus(status: AuthStatus.unauthenticated)); + } on FlowExpiredException catch (e) { + // get new settings flow + add(GetSettingsFlow(flowId: e.flowId)); + } on UnknownException catch (e) { + emit(state.copyWith(isLoading: false, message: e.message)); + } catch (_) { + emit(state.copyWith(isLoading: false)); } } @@ -67,8 +82,11 @@ class SettingsBloc extends Bloc { UpdateSettingsFlow event, Emitter emit) async { try { if (state.settingsFlow != null) { + List updatedConditions = List.from(state.conditions); + updatedConditions + .removeWhere((element) => element is SessionRefreshRequested); emit(state.copyWith( - isLoading: true, isSessionRefreshRequired: false, message: null)); + isLoading: true, conditions: updatedConditions, message: null)); final settings = await repository.updateSettingsFlow( flowId: state.settingsFlow!.id, group: event.group, @@ -83,7 +101,10 @@ class SettingsBloc extends Bloc { add(GetSettingsFlow(flowId: e.flowId)); } on SessionRefreshRequiredException catch (_) { // set session refresh required flag to navigate to login page - emit(state.copyWith(isSessionRefreshRequired: true, isLoading: false)); + List currentConditions = + List.from(state.conditions, growable: true); + currentConditions.add(SessionRefreshRequested()); + emit(state.copyWith(conditions: currentConditions, isLoading: false)); } on UnknownException catch (e) { emit(state.copyWith(isLoading: false, message: e.message)); } catch (_) { diff --git a/flutter-ory-network/lib/blocs/settings/settings_bloc.freezed.dart b/flutter-ory-network/lib/blocs/settings/settings_bloc.freezed.dart index d2ed78d3..fe7f5a5d 100644 --- a/flutter-ory-network/lib/blocs/settings/settings_bloc.freezed.dart +++ b/flutter-ory-network/lib/blocs/settings/settings_bloc.freezed.dart @@ -21,7 +21,7 @@ final _privateConstructorUsedError = UnsupportedError( mixin _$SettingsState { SettingsFlow? get settingsFlow => throw _privateConstructorUsedError; bool get isLoading => throw _privateConstructorUsedError; - bool get isSessionRefreshRequired => throw _privateConstructorUsedError; + List get conditions => throw _privateConstructorUsedError; String? get message => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -38,7 +38,7 @@ abstract class $SettingsStateCopyWith<$Res> { $Res call( {SettingsFlow? settingsFlow, bool isLoading, - bool isSessionRefreshRequired, + List conditions, String? message}); } @@ -57,7 +57,7 @@ class _$SettingsStateCopyWithImpl<$Res, $Val extends SettingsState> $Res call({ Object? settingsFlow = freezed, Object? isLoading = null, - Object? isSessionRefreshRequired = null, + Object? conditions = null, Object? message = freezed, }) { return _then(_value.copyWith( @@ -69,10 +69,10 @@ class _$SettingsStateCopyWithImpl<$Res, $Val extends SettingsState> ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool, - isSessionRefreshRequired: null == isSessionRefreshRequired - ? _value.isSessionRefreshRequired - : isSessionRefreshRequired // ignore: cast_nullable_to_non_nullable - as bool, + conditions: null == conditions + ? _value.conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, message: freezed == message ? _value.message : message // ignore: cast_nullable_to_non_nullable @@ -92,7 +92,7 @@ abstract class _$$SettingsStateImplCopyWith<$Res> $Res call( {SettingsFlow? settingsFlow, bool isLoading, - bool isSessionRefreshRequired, + List conditions, String? message}); } @@ -109,7 +109,7 @@ class __$$SettingsStateImplCopyWithImpl<$Res> $Res call({ Object? settingsFlow = freezed, Object? isLoading = null, - Object? isSessionRefreshRequired = null, + Object? conditions = null, Object? message = freezed, }) { return _then(_$SettingsStateImpl( @@ -121,10 +121,10 @@ class __$$SettingsStateImplCopyWithImpl<$Res> ? _value.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool, - isSessionRefreshRequired: null == isSessionRefreshRequired - ? _value.isSessionRefreshRequired - : isSessionRefreshRequired // ignore: cast_nullable_to_non_nullable - as bool, + conditions: null == conditions + ? _value._conditions + : conditions // ignore: cast_nullable_to_non_nullable + as List, message: freezed == message ? _value.message : message // ignore: cast_nullable_to_non_nullable @@ -139,23 +139,30 @@ class _$SettingsStateImpl implements _SettingsState { const _$SettingsStateImpl( {this.settingsFlow, this.isLoading = false, - this.isSessionRefreshRequired = false, - this.message}); + final List conditions = const [], + this.message}) + : _conditions = conditions; @override final SettingsFlow? settingsFlow; @override @JsonKey() final bool isLoading; + final List _conditions; @override @JsonKey() - final bool isSessionRefreshRequired; + List get conditions { + if (_conditions is EqualUnmodifiableListView) return _conditions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_conditions); + } + @override final String? message; @override String toString() { - return 'SettingsState(settingsFlow: $settingsFlow, isLoading: $isLoading, isSessionRefreshRequired: $isSessionRefreshRequired, message: $message)'; + return 'SettingsState(settingsFlow: $settingsFlow, isLoading: $isLoading, conditions: $conditions, message: $message)'; } @override @@ -167,15 +174,14 @@ class _$SettingsStateImpl implements _SettingsState { other.settingsFlow == settingsFlow) && (identical(other.isLoading, isLoading) || other.isLoading == isLoading) && - (identical( - other.isSessionRefreshRequired, isSessionRefreshRequired) || - other.isSessionRefreshRequired == isSessionRefreshRequired) && + const DeepCollectionEquality() + .equals(other._conditions, _conditions) && (identical(other.message, message) || other.message == message)); } @override - int get hashCode => Object.hash( - runtimeType, settingsFlow, isLoading, isSessionRefreshRequired, message); + int get hashCode => Object.hash(runtimeType, settingsFlow, isLoading, + const DeepCollectionEquality().hash(_conditions), message); @JsonKey(ignore: true) @override @@ -188,7 +194,7 @@ abstract class _SettingsState implements SettingsState { const factory _SettingsState( {final SettingsFlow? settingsFlow, final bool isLoading, - final bool isSessionRefreshRequired, + final List conditions, final String? message}) = _$SettingsStateImpl; @override @@ -196,7 +202,7 @@ abstract class _SettingsState implements SettingsState { @override bool get isLoading; @override - bool get isSessionRefreshRequired; + List get conditions; @override String? get message; @override diff --git a/flutter-ory-network/lib/blocs/settings/settings_state.dart b/flutter-ory-network/lib/blocs/settings/settings_state.dart index 235002ba..7b3cee52 100644 --- a/flutter-ory-network/lib/blocs/settings/settings_state.dart +++ b/flutter-ory-network/lib/blocs/settings/settings_state.dart @@ -8,6 +8,6 @@ sealed class SettingsState with _$SettingsState { const factory SettingsState( {SettingsFlow? settingsFlow, @Default(false) bool isLoading, - @Default(false) bool isSessionRefreshRequired, + @Default([]) List conditions, String? message}) = _SettingsState; } diff --git a/flutter-ory-network/lib/main.dart b/flutter-ory-network/lib/main.dart index 0dec1c29..172a9cf6 100644 --- a/flutter-ory-network/lib/main.dart +++ b/flutter-ory-network/lib/main.dart @@ -1,12 +1,15 @@ // Copyright © 2023 Ory Corp // SPDX-License-Identifier: Apache-2.0 +import 'package:collection/collection.dart'; import 'package:dio/dio.dart'; import 'package:dio/io.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:google_sign_in/google_sign_in.dart'; +import 'package:ory_network_flutter/pages/settings.dart'; +import 'package:ory_network_flutter/widgets/helpers.dart'; import 'package:ory_network_flutter/widgets/ory_theme.dart'; import 'dart:io' show Platform; @@ -103,16 +106,33 @@ class _MyAppViewState extends State { builder: (BuildContext context) => const LoginPage(aal: 'aal1')), (Route route) => false); - }, authenticated: (_) { - _navigator.pushAndRemoveUntil( - MaterialPageRoute( - builder: (BuildContext context) => const HomePage()), - (Route route) => false); - }, aal2Requested: (_) { + }, authenticated: (authState) { + // if user is authenticated and didn't request a recovery, + // navigate to home page + if (!isRecoveryRequired(authState.conditions)) { + _navigator.pushAndRemoveUntil( + MaterialPageRoute( + builder: (BuildContext context) => const HomePage()), + (Route route) => false); + } else { + // otherwise, navigate to settings page + // with provided settings flow id + final recovery = authState.conditions.firstWhereOrNull( + (element) => element is RecoveryRequested)! + as RecoveryRequested; + + _navigator.pushAndRemoveUntil( + MaterialPageRoute( + builder: (BuildContext context) => SettingsPage( + flowId: recovery.settingsFlowId, + )), + (route) => false); + } + }, aal2Requested: (authState) { _navigator.pushAndRemoveUntil( MaterialPageRoute( - builder: (BuildContext context) => - const LoginPage(aal: 'aal2')), + builder: (BuildContext context) => LoginPage( + conditions: authState.conditions, aal: 'aal2')), (Route route) => false); }); }, diff --git a/flutter-ory-network/lib/pages/login.dart b/flutter-ory-network/lib/pages/login.dart index 796c0d1f..7193915e 100644 --- a/flutter-ory-network/lib/pages/login.dart +++ b/flutter-ory-network/lib/pages/login.dart @@ -9,17 +9,18 @@ import '../blocs/auth/auth_bloc.dart'; import '../blocs/login/login_bloc.dart'; import '../repositories/auth.dart'; import '../widgets/helpers.dart'; +import 'recovery.dart'; import 'registration.dart'; class LoginPage extends StatelessWidget { - final bool isSessionRefresh; + final List conditions; final String aal; - const LoginPage( - {super.key, this.isSessionRefresh = false, required this.aal}); + const LoginPage({super.key, this.conditions = const [], required this.aal}); @override Widget build(BuildContext context) { + final sessionRefreshRequested = isSessionRefreshRequired(conditions); return BlocListener( // navigate to previous page only if the user refreshed the session listenWhen: (previous, current) { @@ -27,17 +28,18 @@ class LoginPage extends StatelessWidget { previous.mapOrNull(authenticated: (value) => value.session); final currentSession = current.mapOrNull(authenticated: (value) => value.session); + final sessionRefreshRequested = isSessionRefreshRequired(conditions); return previousSession != currentSession && previousSession != null && currentSession != null && - isSessionRefresh; + sessionRefreshRequested; }, listener: (context, state) { Navigator.of(context).pop(true); }, child: Scaffold( - extendBodyBehindAppBar: !isSessionRefresh, - appBar: isSessionRefresh + extendBodyBehindAppBar: !sessionRefreshRequested, + appBar: sessionRefreshRequested ? AppBar( backgroundColor: Colors.transparent, elevation: 0, @@ -68,9 +70,10 @@ class LoginPage extends StatelessWidget { body: BlocProvider( create: (context) => LoginBloc( authBloc: context.read(), - repository: RepositoryProvider.of(context)) - ..add(CreateLoginFlow(aal: aal, refresh: isSessionRefresh)), - child: LoginForm(isSessionRefresh: isSessionRefresh)), + repository: RepositoryProvider.of(context), + conditions: conditions) + ..add(CreateLoginFlow(aal: aal)), + child: LoginForm(isSessionRefresh: sessionRefreshRequested)), ), ); } @@ -165,8 +168,26 @@ class LoginForm extends StatelessWidget { buildGroup(context, UiNodeGroupEnum.code, codeNodes, _onInputChange, _onInputSubmit), if (passwordNodes.isNotEmpty) - buildGroup(context, UiNodeGroupEnum.password, - passwordNodes, _onInputChange, _onInputSubmit), + Column( + children: [ + buildGroup(context, UiNodeGroupEnum.password, + passwordNodes, _onInputChange, _onInputSubmit), + Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Row( + children: [ + TextButton( + onPressed: () => Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + const RecoveryPage())), + child: const Text("Forgot password?"), + ), + ], + ), + ), + ], + ), if (lookupSecretNodes.isNotEmpty) buildGroup(context, UiNodeGroupEnum.lookupSecret, lookupSecretNodes, _onInputChange, _onInputSubmit), diff --git a/flutter-ory-network/lib/pages/recovery.dart b/flutter-ory-network/lib/pages/recovery.dart new file mode 100644 index 00000000..7fdc1524 --- /dev/null +++ b/flutter-ory-network/lib/pages/recovery.dart @@ -0,0 +1,193 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:ory_client/ory_client.dart'; +import 'package:ory_network_flutter/blocs/bloc/recovery_bloc.dart'; +import 'package:ory_network_flutter/repositories/auth.dart'; +import 'package:ory_network_flutter/widgets/helpers.dart'; + +import '../blocs/auth/auth_bloc.dart'; + +class RecoveryPage extends StatelessWidget { + const RecoveryPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leadingWidth: 72, + toolbarHeight: 72, + // use row to avoid force resizing of leading widget + leading: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 32, top: 32), + child: GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: Container( + height: 40, + width: 40, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all( + width: 1, color: const Color(0xFFE2E8F0))), + child: const Icon(Icons.arrow_back, size: 16), + ), + ), + ), + ], + )), + body: BlocProvider( + create: (context) => RecoveryBloc( + repository: RepositoryProvider.of(context)) + ..add(CreateRecoveryFlow()), + child: const RecoveryForm(), + )); + } +} + +class RecoveryForm extends StatelessWidget { + const RecoveryForm({super.key}); + + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) { + // recovery flow was successful, + // get session information + if (state.settingsFlowId != null) { + final authBloc = (context).read(); + authBloc.add(GetCurrentSessionInformation(conditions: [ + RecoveryRequested(settingsFlowId: state.settingsFlowId!) + ])); + } + }, + child: BlocBuilder( + buildWhen: (previous, current) => + previous.isLoading != current.isLoading, + builder: (context, state) { + if (state.recoveryFlow != null) { + return _buildUi(context, state); + } else { + return buildFlowNotCreated(context, state.message); + } + }, + )); + } + + _buildUi(BuildContext context, RecoveryState state) { + final nodes = state.recoveryFlow!.ui.nodes; + + // get default nodes from all nodes + final defaultNodes = nodes.where((node) { + if (node.group == UiNodeGroupEnum.default_) { + if (node.attributes.oneOf.isType(UiNodeInputAttributes)) { + final attributes = + node.attributes.oneOf.value as UiNodeInputAttributes; + if (attributes.type == UiNodeInputAttributesTypeEnum.hidden) { + return false; + } else { + return true; + } + } + } + return false; + }).toList(); + + // get code nodes from all nodes + final codeNodes = nodes.where((node) { + if (node.group == UiNodeGroupEnum.code) { + if (node.attributes.oneOf.isType(UiNodeInputAttributes)) { + final attributes = + node.attributes.oneOf.value as UiNodeInputAttributes; + if (attributes.type == UiNodeInputAttributesTypeEnum.hidden) { + return false; + } else { + return true; + } + } + } + return false; + }).toList(); + + return Stack(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: SingleChildScrollView( + // do not show scrolling indicator + physics: const BouncingScrollPhysics(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Padding( + padding: EdgeInsets.symmetric(vertical: 32), + child: Text('Recovery', + style: TextStyle( + fontWeight: FontWeight.w600, + height: 1.5, + fontSize: 18))), + if (defaultNodes.isNotEmpty) + buildGroup(context, UiNodeGroupEnum.default_, + defaultNodes, _onInputChange, _onInputSubmit), + if (codeNodes.isNotEmpty) + buildGroup(context, UiNodeGroupEnum.code, + codeNodes, _onInputChange, _onInputSubmit), + const SizedBox( + height: 32, + ), + if (state.recoveryFlow?.ui.messages != null) + for (var message in state.recoveryFlow!.ui.messages!) + Text( + message.text, + style: TextStyle(color: getMessageColor(message.type)), + ), + ], + ), + ), + ), + // build progress indicator when state is loading + BlocSelector( + bloc: (context).read(), + selector: (RecoveryState state) => state.isLoading, + builder: (BuildContext context, bool isLoading) { + if (isLoading) { + return const Opacity( + opacity: 0.8, + child: ModalBarrier(dismissible: false, color: Colors.white30), + ); + } else { + return Container(); + } + }), + BlocSelector( + bloc: (context).read(), + selector: (RecoveryState state) => state.isLoading, + builder: (BuildContext context, bool isLoading) { + if (isLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else { + return Container(); + } + }) + ]); + } + + _onInputChange(BuildContext context, String value, String name) { + context.read().add(ChangeNodeValue(value: value, name: name)); + } + + _onInputSubmit( + BuildContext context, UiNodeGroupEnum group, String name, String value) { + context + .read() + .add(UpdateRecoveryFlow(group: group, name: name, value: value)); + } +} diff --git a/flutter-ory-network/lib/pages/settings.dart b/flutter-ory-network/lib/pages/settings.dart index fb5553b9..3ed174f6 100644 --- a/flutter-ory-network/lib/pages/settings.dart +++ b/flutter-ory-network/lib/pages/settings.dart @@ -10,10 +10,12 @@ import '../blocs/auth/auth_bloc.dart'; import '../blocs/settings/settings_bloc.dart'; import '../repositories/auth.dart'; import '../widgets/helpers.dart'; +import 'home.dart'; import 'login.dart'; class SettingsPage extends StatelessWidget { - const SettingsPage({super.key}); + final String? flowId; + const SettingsPage({super.key, this.flowId}); @override Widget build(BuildContext context) { @@ -29,19 +31,36 @@ class SettingsPage extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.only(left: 32, top: 32), - child: GestureDetector( - onTap: () => Navigator.of(context).pop(), - child: Container( - height: 40, - width: 40, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - border: Border.all( - width: 1, color: const Color(0xFFE2E8F0))), - child: const Icon(Icons.arrow_back, size: 16), - ), - ), + child: !Navigator.of(context).canPop() + ? GestureDetector( + onTap: () => Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (BuildContext context) => + const HomePage())), + child: Container( + height: 40, + width: 40, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all( + width: 1, color: const Color(0xFFE2E8F0))), + child: const Icon(Icons.cancel, size: 16), + ), + ) + : GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: Container( + height: 40, + width: 40, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all( + width: 1, color: const Color(0xFFE2E8F0))), + child: const Icon(Icons.arrow_back, size: 16), + ), + ), ), ], )), @@ -49,7 +68,9 @@ class SettingsPage extends StatelessWidget { create: (context) => SettingsBloc( authBloc: context.read(), repository: SettingsRepository(service: service)) - ..add(CreateSettingsFlow()), + ..add(flowId != null + ? GetSettingsFlow(flowId: flowId!) + : CreateSettingsFlow()), child: const SettingsForm()), ); } @@ -65,17 +86,21 @@ class SettingsForm extends StatelessWidget { listeners: [ BlocListener( bloc: settingsBloc, - listenWhen: (SettingsState previous, SettingsState current) => - previous.isSessionRefreshRequired != - current.isSessionRefreshRequired, + listenWhen: (SettingsState previous, SettingsState current) { + final wasSessionRefreshRequested = + isSessionRefreshRequired(previous.conditions); + final isSessionRefreshRequested = + isSessionRefreshRequired(current.conditions); + return wasSessionRefreshRequested != isSessionRefreshRequested; + }, listener: (BuildContext context, SettingsState state) async { // if session needs to be refreshed, navigate to login flow screen - if (state.isSessionRefreshRequired) { + if (isSessionRefreshRequired(state.conditions)) { await Navigator.push( context, MaterialPageRoute( - builder: (context) => const LoginPage( - isSessionRefresh: true, + builder: (context) => LoginPage( + conditions: [SessionRefreshRequested()], aal: 'aal1', ))).then((value) { // retry updating settings when session was refreshed @@ -98,12 +123,13 @@ class SettingsForm extends StatelessWidget { listenWhen: (SettingsState previous, SettingsState current) => // listen to changes only when current // state is not loading (e.g. updating settings), - // previous and current messages differ + // previous state was loading, + // there is a new message, // and session refresh is not required !current.isLoading && - current.settingsFlow?.ui.messages != - previous.settingsFlow?.ui.messages && - !current.isSessionRefreshRequired, + previous.isLoading && + current.settingsFlow?.ui.messages != null && + !isSessionRefreshRequired(current.conditions), listener: (BuildContext context, SettingsState state) { if (state.settingsFlow!.ui.messages != null) { // for simplicity, we will only show the first message in snackbar @@ -128,6 +154,14 @@ class SettingsForm extends StatelessWidget { content: Text(state.message!), )); } + }), + // remove snackbars when loading + BlocListener( + bloc: settingsBloc, + listener: (BuildContext context, SettingsState state) { + if (state.isLoading) { + ScaffoldMessenger.of(context).clearSnackBars(); + } }) ], child: BlocBuilder( diff --git a/flutter-ory-network/lib/repositories/auth.dart b/flutter-ory-network/lib/repositories/auth.dart index 2dbb126d..307909cb 100644 --- a/flutter-ory-network/lib/repositories/auth.dart +++ b/flutter-ory-network/lib/repositories/auth.dart @@ -50,6 +50,11 @@ class AuthRepository { return flow; } + Future createRecoveryFlow() async { + final flow = await service.createRecoveryFlow(); + return flow; + } + Future getLoginFlow({required String flowId}) async { final flow = await service.getLoginFlow(flowId: flowId); return flow; @@ -153,6 +158,22 @@ class AuthRepository { return session; } + Future updateRecoveryFlow( + {required String flowId, + required UiNodeGroupEnum group, + required String name, + required String value, + required List nodes}) async { + // create request body + var body = _createRequestBody( + group: group, name: name, value: value, nodes: nodes); + + // submit recovery + final recovery = + await service.updateRecoveryFlow(flowId: flowId, value: body); + return recovery; + } + Map _getMapFromJWT(String splittedToken) { String normalizedSource = base64Url.normalize(splittedToken); return jsonDecode(utf8.decode(base64Url.decode(normalizedSource))); @@ -264,28 +285,36 @@ class AuthRepository { } RegistrationFlow changeRegistrationNodeValue( - {required RegistrationFlow settings, + {required RegistrationFlow flow, required String name, required String value}) { // update node value final updatedNodes = - updateNodes(nodes: settings.ui.nodes, name: name, value: value); - // update settings' node - final newFlow = - settings.rebuild((p0) => p0..ui.nodes.replace(updatedNodes)); + updateNodes(nodes: flow.ui.nodes, name: name, value: value); + // update registration flow + final newFlow = flow.rebuild((p0) => p0..ui.nodes.replace(updatedNodes)); return newFlow; } LoginFlow changeLoginNodeValue( - {required LoginFlow settings, + {required LoginFlow flow, required String name, required String value}) { + // update node value + final updatedNodes = + updateNodes(nodes: flow.ui.nodes, name: name, value: value); + // update login flow + final newFlow = flow.rebuild((p0) => p0..ui.nodes.replace(updatedNodes)); + return newFlow; + } + + RecoveryFlow changeRecoveryNodeValue( + {required RecoveryFlow flow, required String name, required String value}) { // update node value final updatedNodes = - updateNodes(nodes: settings.ui.nodes, name: name, value: value); - // update settings' node - final newFlow = - settings.rebuild((p0) => p0..ui.nodes.replace(updatedNodes)); + updateNodes(nodes: flow.ui.nodes, name: name, value: value); + // update login flow + final newFlow = flow.rebuild((p0) => p0..ui.nodes.replace(updatedNodes)); return newFlow; } diff --git a/flutter-ory-network/lib/services/auth.dart b/flutter-ory-network/lib/services/auth.dart index a07afc50..e66f3c4c 100644 --- a/flutter-ory-network/lib/services/auth.dart +++ b/flutter-ory-network/lib/services/auth.dart @@ -53,7 +53,7 @@ class AuthService { returnSessionTokenExchangeCode: true, returnTo: 'ory://flutter-ory-network'); if (response.data != null) { - // return flow id + // return flow return response.data!; } else { throw const CustomException.unknown(); @@ -70,7 +70,22 @@ class AuthService { returnSessionTokenExchangeCode: true, returnTo: 'ory://flutter-ory-network'); if (response.data != null) { - // return flow id + // return flow + return response.data!; + } else { + throw const CustomException.unknown(); + } + } on DioException catch (e) { + throw _handleUnknownException(e.response?.data); + } + } + + /// Create recovery flow + Future createRecoveryFlow() async { + try { + final response = await _ory.createNativeRecoveryFlow(); + if (response.data != null) { + // return flow return response.data!; } else { throw const CustomException.unknown(); @@ -327,7 +342,68 @@ class AuthService { } } - /// Log out + /// Update recovery flow with [flowId] and [value] as body + Future updateRecoveryFlow( + {required String flowId, required Map value}) async { + try { + final oneOf = OneOf.fromValue1( + value: UpdateRecoveryFlowWithCodeMethod((b) => b + ..method = UpdateRecoveryFlowWithCodeMethodMethodEnum.code + ..email = value['email'] + ..code = value['code'])); + + final response = await _ory.updateRecoveryFlow( + flow: flowId, + updateRecoveryFlowBody: + UpdateRecoveryFlowBody((b) => b..oneOf = oneOf)); + if (response.data != null) { + if (response.data!.continueWith != null) { + // get session token from actions + final sessionTokenAction = response.data!.continueWith!.firstWhere( + (element) => + element.oneOf.isType(ContinueWithSetOrySessionToken)); + final token = + (sessionTokenAction.oneOf.value as ContinueWithSetOrySessionToken) + .orySessionToken; + // save session token + await _storage.persistToken(token); + // get flow id to redirect to settings and let the user change the password + final settingsFlowAction = response.data!.continueWith!.firstWhere( + (element) => element.oneOf.isType(ContinueWithSettingsUi)); + final settingsFlowId = + (settingsFlowAction.oneOf.value as ContinueWithSettingsUi) + .flow + .id; + throw CustomException.settingsRedirectRequired( + settingsFlowId: settingsFlowId); + } + return response.data!; + } else { + throw const CustomException.unknown(); + } + } on DioException catch (e) { + if (e.response?.statusCode == 400) { + final recoveryFlow = standardSerializers.deserializeWith( + RecoveryFlow.serializer, e.response?.data); + if (recoveryFlow != null) { + throw CustomException.badRequest(flow: recoveryFlow); + } else { + throw const CustomException.unknown(); + } + } else if (e.response?.statusCode == 410) { + // recovery flow expired, use new flow id and add error message + throw CustomException.flowExpired( + flowId: e.response?.data['use_flow_id']); + } else { + throw _handleUnknownException(e.response?.data); + } + } on CustomException catch (_) { + rethrow; + } catch (e) { + throw const CustomException.unknown(); + } + } + Future logout() async { try { final token = await _storage.getToken(); diff --git a/flutter-ory-network/lib/services/exceptions.dart b/flutter-ory-network/lib/services/exceptions.dart index 3215c58e..32c9803d 100644 --- a/flutter-ory-network/lib/services/exceptions.dart +++ b/flutter-ory-network/lib/services/exceptions.dart @@ -21,6 +21,8 @@ sealed class CustomException with _$CustomException { TwoFactorAuthRequiredException; const factory CustomException.locationChangeRequired({required String url}) = LocationChangeRequiredException; + const factory CustomException.settingsRedirectRequired( + {String? settingsFlowId}) = settingsRedirectRequired; const factory CustomException.unknown( {@Default('An error occured. Please try again later.') String message}) = UnknownException; diff --git a/flutter-ory-network/lib/services/exceptions.freezed.dart b/flutter-ory-network/lib/services/exceptions.freezed.dart index b5b9ed62..1ffb377d 100644 --- a/flutter-ory-network/lib/services/exceptions.freezed.dart +++ b/flutter-ory-network/lib/services/exceptions.freezed.dart @@ -27,6 +27,7 @@ mixin _$CustomException { required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) => throw _privateConstructorUsedError; @@ -38,6 +39,7 @@ mixin _$CustomException { TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) => throw _privateConstructorUsedError; @@ -49,6 +51,7 @@ mixin _$CustomException { TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) => @@ -64,6 +67,8 @@ mixin _$CustomException { twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) => throw _privateConstructorUsedError; @@ -78,6 +83,8 @@ mixin _$CustomException { twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) => throw _privateConstructorUsedError; @@ -92,6 +99,8 @@ mixin _$CustomException { twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) => @@ -201,6 +210,7 @@ class _$SessionRefreshRequiredExceptionImpl required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) { return sessionRefreshRequired(message); @@ -215,6 +225,7 @@ class _$SessionRefreshRequiredExceptionImpl TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) { return sessionRefreshRequired?.call(message); @@ -229,6 +240,7 @@ class _$SessionRefreshRequiredExceptionImpl TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) { @@ -250,6 +262,8 @@ class _$SessionRefreshRequiredExceptionImpl twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) { return sessionRefreshRequired(this); @@ -267,6 +281,8 @@ class _$SessionRefreshRequiredExceptionImpl twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) { return sessionRefreshRequired?.call(this); @@ -284,6 +300,8 @@ class _$SessionRefreshRequiredExceptionImpl twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) { @@ -387,6 +405,7 @@ class _$BadRequestExceptionImpl extends BadRequestException required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) { return badRequest(flow); @@ -401,6 +420,7 @@ class _$BadRequestExceptionImpl extends BadRequestException TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) { return badRequest?.call(flow); @@ -415,6 +435,7 @@ class _$BadRequestExceptionImpl extends BadRequestException TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) { @@ -436,6 +457,8 @@ class _$BadRequestExceptionImpl extends BadRequestException twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) { return badRequest(this); @@ -453,6 +476,8 @@ class _$BadRequestExceptionImpl extends BadRequestException twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) { return badRequest?.call(this); @@ -470,6 +495,8 @@ class _$BadRequestExceptionImpl extends BadRequestException twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) { @@ -547,6 +574,7 @@ class _$UnauthorizedExceptionImpl extends UnauthorizedException required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) { return unauthorized(); @@ -561,6 +589,7 @@ class _$UnauthorizedExceptionImpl extends UnauthorizedException TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) { return unauthorized?.call(); @@ -575,6 +604,7 @@ class _$UnauthorizedExceptionImpl extends UnauthorizedException TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) { @@ -596,6 +626,8 @@ class _$UnauthorizedExceptionImpl extends UnauthorizedException twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) { return unauthorized(this); @@ -613,6 +645,8 @@ class _$UnauthorizedExceptionImpl extends UnauthorizedException twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) { return unauthorized?.call(this); @@ -630,6 +664,8 @@ class _$UnauthorizedExceptionImpl extends UnauthorizedException twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) { @@ -737,6 +773,7 @@ class _$FlowExpiredExceptionImpl extends FlowExpiredException required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) { return flowExpired(flowId, message); @@ -751,6 +788,7 @@ class _$FlowExpiredExceptionImpl extends FlowExpiredException TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) { return flowExpired?.call(flowId, message); @@ -765,6 +803,7 @@ class _$FlowExpiredExceptionImpl extends FlowExpiredException TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) { @@ -786,6 +825,8 @@ class _$FlowExpiredExceptionImpl extends FlowExpiredException twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) { return flowExpired(this); @@ -803,6 +844,8 @@ class _$FlowExpiredExceptionImpl extends FlowExpiredException twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) { return flowExpired?.call(this); @@ -820,6 +863,8 @@ class _$FlowExpiredExceptionImpl extends FlowExpiredException twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) { @@ -928,6 +973,7 @@ class _$TwoFactorAuthRequiredExceptionImpl required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) { return twoFactorAuthRequired(session); @@ -942,6 +988,7 @@ class _$TwoFactorAuthRequiredExceptionImpl TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) { return twoFactorAuthRequired?.call(session); @@ -956,6 +1003,7 @@ class _$TwoFactorAuthRequiredExceptionImpl TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) { @@ -977,6 +1025,8 @@ class _$TwoFactorAuthRequiredExceptionImpl twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) { return twoFactorAuthRequired(this); @@ -994,6 +1044,8 @@ class _$TwoFactorAuthRequiredExceptionImpl twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) { return twoFactorAuthRequired?.call(this); @@ -1011,6 +1063,8 @@ class _$TwoFactorAuthRequiredExceptionImpl twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) { @@ -1118,6 +1172,7 @@ class _$LocationChangeRequiredExceptionImpl required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) { return locationChangeRequired(url); @@ -1132,6 +1187,7 @@ class _$LocationChangeRequiredExceptionImpl TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) { return locationChangeRequired?.call(url); @@ -1146,6 +1202,7 @@ class _$LocationChangeRequiredExceptionImpl TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) { @@ -1167,6 +1224,8 @@ class _$LocationChangeRequiredExceptionImpl twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) { return locationChangeRequired(this); @@ -1184,6 +1243,8 @@ class _$LocationChangeRequiredExceptionImpl twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) { return locationChangeRequired?.call(this); @@ -1201,6 +1262,8 @@ class _$LocationChangeRequiredExceptionImpl twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) { @@ -1223,6 +1286,204 @@ abstract class LocationChangeRequiredException extends CustomException { get copyWith => throw _privateConstructorUsedError; } +/// @nodoc +abstract class _$$settingsRedirectRequiredImplCopyWith { + factory _$$settingsRedirectRequiredImplCopyWith( + _$settingsRedirectRequiredImpl value, + $Res Function(_$settingsRedirectRequiredImpl) then) = + __$$settingsRedirectRequiredImplCopyWithImpl; + @useResult + $Res call({String? settingsFlowId}); +} + +/// @nodoc +class __$$settingsRedirectRequiredImplCopyWithImpl + extends _$CustomExceptionCopyWithImpl> + implements _$$settingsRedirectRequiredImplCopyWith { + __$$settingsRedirectRequiredImplCopyWithImpl( + _$settingsRedirectRequiredImpl _value, + $Res Function(_$settingsRedirectRequiredImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? settingsFlowId = freezed, + }) { + return _then(_$settingsRedirectRequiredImpl( + settingsFlowId: freezed == settingsFlowId + ? _value.settingsFlowId + : settingsFlowId // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc + +class _$settingsRedirectRequiredImpl extends settingsRedirectRequired + with DiagnosticableTreeMixin { + const _$settingsRedirectRequiredImpl({this.settingsFlowId}) : super._(); + + @override + final String? settingsFlowId; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'CustomException<$T>.settingsRedirectRequired(settingsFlowId: $settingsFlowId)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty( + 'type', 'CustomException<$T>.settingsRedirectRequired')) + ..add(DiagnosticsProperty('settingsFlowId', settingsFlowId)); + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$settingsRedirectRequiredImpl && + (identical(other.settingsFlowId, settingsFlowId) || + other.settingsFlowId == settingsFlowId)); + } + + @override + int get hashCode => Object.hash(runtimeType, settingsFlowId); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$settingsRedirectRequiredImplCopyWith> + get copyWith => __$$settingsRedirectRequiredImplCopyWithImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String? message) sessionRefreshRequired, + required TResult Function(T flow) badRequest, + required TResult Function() unauthorized, + required TResult Function(String flowId, String? message) flowExpired, + required TResult Function(Session? session) twoFactorAuthRequired, + required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, + required TResult Function(String message) unknown, + }) { + return settingsRedirectRequired(settingsFlowId); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String? message)? sessionRefreshRequired, + TResult? Function(T flow)? badRequest, + TResult? Function()? unauthorized, + TResult? Function(String flowId, String? message)? flowExpired, + TResult? Function(Session? session)? twoFactorAuthRequired, + TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, + TResult? Function(String message)? unknown, + }) { + return settingsRedirectRequired?.call(settingsFlowId); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String? message)? sessionRefreshRequired, + TResult Function(T flow)? badRequest, + TResult Function()? unauthorized, + TResult Function(String flowId, String? message)? flowExpired, + TResult Function(Session? session)? twoFactorAuthRequired, + TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, + TResult Function(String message)? unknown, + required TResult orElse(), + }) { + if (settingsRedirectRequired != null) { + return settingsRedirectRequired(settingsFlowId); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(SessionRefreshRequiredException value) + sessionRefreshRequired, + required TResult Function(BadRequestException value) badRequest, + required TResult Function(UnauthorizedException value) unauthorized, + required TResult Function(FlowExpiredException value) flowExpired, + required TResult Function(TwoFactorAuthRequiredException value) + twoFactorAuthRequired, + required TResult Function(LocationChangeRequiredException value) + locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, + required TResult Function(UnknownException value) unknown, + }) { + return settingsRedirectRequired(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(SessionRefreshRequiredException value)? + sessionRefreshRequired, + TResult? Function(BadRequestException value)? badRequest, + TResult? Function(UnauthorizedException value)? unauthorized, + TResult? Function(FlowExpiredException value)? flowExpired, + TResult? Function(TwoFactorAuthRequiredException value)? + twoFactorAuthRequired, + TResult? Function(LocationChangeRequiredException value)? + locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, + TResult? Function(UnknownException value)? unknown, + }) { + return settingsRedirectRequired?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(SessionRefreshRequiredException value)? + sessionRefreshRequired, + TResult Function(BadRequestException value)? badRequest, + TResult Function(UnauthorizedException value)? unauthorized, + TResult Function(FlowExpiredException value)? flowExpired, + TResult Function(TwoFactorAuthRequiredException value)? + twoFactorAuthRequired, + TResult Function(LocationChangeRequiredException value)? + locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, + TResult Function(UnknownException value)? unknown, + required TResult orElse(), + }) { + if (settingsRedirectRequired != null) { + return settingsRedirectRequired(this); + } + return orElse(); + } +} + +abstract class settingsRedirectRequired extends CustomException { + const factory settingsRedirectRequired({final String? settingsFlowId}) = + _$settingsRedirectRequiredImpl; + const settingsRedirectRequired._() : super._(); + + String? get settingsFlowId; + @JsonKey(ignore: true) + _$$settingsRedirectRequiredImplCopyWith> + get copyWith => throw _privateConstructorUsedError; +} + /// @nodoc abstract class _$$UnknownExceptionImplCopyWith { factory _$$UnknownExceptionImplCopyWith(_$UnknownExceptionImpl value, @@ -1306,6 +1567,7 @@ class _$UnknownExceptionImpl extends UnknownException required TResult Function(String flowId, String? message) flowExpired, required TResult Function(Session? session) twoFactorAuthRequired, required TResult Function(String url) locationChangeRequired, + required TResult Function(String? settingsFlowId) settingsRedirectRequired, required TResult Function(String message) unknown, }) { return unknown(message); @@ -1320,6 +1582,7 @@ class _$UnknownExceptionImpl extends UnknownException TResult? Function(String flowId, String? message)? flowExpired, TResult? Function(Session? session)? twoFactorAuthRequired, TResult? Function(String url)? locationChangeRequired, + TResult? Function(String? settingsFlowId)? settingsRedirectRequired, TResult? Function(String message)? unknown, }) { return unknown?.call(message); @@ -1334,6 +1597,7 @@ class _$UnknownExceptionImpl extends UnknownException TResult Function(String flowId, String? message)? flowExpired, TResult Function(Session? session)? twoFactorAuthRequired, TResult Function(String url)? locationChangeRequired, + TResult Function(String? settingsFlowId)? settingsRedirectRequired, TResult Function(String message)? unknown, required TResult orElse(), }) { @@ -1355,6 +1619,8 @@ class _$UnknownExceptionImpl extends UnknownException twoFactorAuthRequired, required TResult Function(LocationChangeRequiredException value) locationChangeRequired, + required TResult Function(settingsRedirectRequired value) + settingsRedirectRequired, required TResult Function(UnknownException value) unknown, }) { return unknown(this); @@ -1372,6 +1638,8 @@ class _$UnknownExceptionImpl extends UnknownException twoFactorAuthRequired, TResult? Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult? Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult? Function(UnknownException value)? unknown, }) { return unknown?.call(this); @@ -1389,6 +1657,8 @@ class _$UnknownExceptionImpl extends UnknownException twoFactorAuthRequired, TResult Function(LocationChangeRequiredException value)? locationChangeRequired, + TResult Function(settingsRedirectRequired value)? + settingsRedirectRequired, TResult Function(UnknownException value)? unknown, required TResult orElse(), }) { diff --git a/flutter-ory-network/lib/widgets/helpers.dart b/flutter-ory-network/lib/widgets/helpers.dart index aead4992..a27c5302 100644 --- a/flutter-ory-network/lib/widgets/helpers.dart +++ b/flutter-ory-network/lib/widgets/helpers.dart @@ -5,9 +5,11 @@ import 'dart:io'; import 'package:bloc/bloc.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:ory_client/ory_client.dart'; +import '../blocs/auth/auth_bloc.dart'; import 'nodes/image.dart'; import 'nodes/input.dart'; import 'nodes/input_submit.dart'; @@ -157,3 +159,15 @@ UiNodeInputAttributes asInputAttributes(UiNode node) { 'attributes of this node are not of type UiNodeInputAttributes'); } } + +bool isSessionRefreshRequired(List conditions) { + final sessionRefreshCondition = conditions + .firstWhereOrNull((element) => element is SessionRefreshRequested); + return sessionRefreshCondition != null; +} + +bool isRecoveryRequired(List conditions) { + final recoveryCondition = + conditions.firstWhereOrNull((element) => element is RecoveryRequested); + return recoveryCondition != null; +} diff --git a/flutter-ory-network/lib/widgets/nodes/input.dart b/flutter-ory-network/lib/widgets/nodes/input.dart index a12fb4a9..cc897218 100644 --- a/flutter-ory-network/lib/widgets/nodes/input.dart +++ b/flutter-ory-network/lib/widgets/nodes/input.dart @@ -5,6 +5,7 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:ory_client/ory_client.dart'; +import 'package:ory_network_flutter/blocs/bloc/recovery_bloc.dart'; import 'package:ory_network_flutter/blocs/login/login_bloc.dart'; import 'package:ory_network_flutter/blocs/registration/registration_bloc.dart'; @@ -98,6 +99,16 @@ class _InputNodeState extends State { return false; } }); + } else if (state is RecoveryState) { + node = state.recoveryFlow?.ui.nodes.firstWhereOrNull((element) { + if (element.attributes.oneOf.isType(UiNodeInputAttributes)) { + return (element.attributes.oneOf.value as UiNodeInputAttributes) + .name == + attributes.name; + } else { + return false; + } + }); } // assign new value of node to text controller diff --git a/flutter-ory-network/pubspec.lock b/flutter-ory-network/pubspec.lock index 171eb735..9353e563 100644 --- a/flutter-ory-network/pubspec.lock +++ b/flutter-ory-network/pubspec.lock @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" build_resolvers: dependency: transitive description: @@ -117,10 +117,10 @@ packages: dependency: "direct main" description: name: built_value - sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e" + sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2" url: "https://pub.dev" source: hosted - version: "8.7.0" + version: "8.8.0" characters: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" + sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.8.0" collection: dependency: "direct main" description: @@ -181,10 +181,10 @@ packages: dependency: transitive description: name: dart_style - sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334 + sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.4" deep_collection: dependency: "direct main" description: @@ -197,10 +197,10 @@ packages: dependency: "direct main" description: name: dio - sha256: "417e2a6f9d83ab396ec38ff4ea5da6c254da71e4db765ad737a42af6930140b7" + sha256: "01870acd87986f768e0c09cc4d7a19a59d814af7b34cbeb0b437d2c33bdfea4c" url: "https://pub.dev" source: hosted - version: "5.3.3" + version: "5.3.4" dotenv: dependency: "direct main" description: @@ -404,10 +404,10 @@ packages: dependency: "direct main" description: name: google_sign_in - sha256: f45038d27bcad37498f282295ae97eece23c9349fc16649154067b87b9f1fd03 + sha256: "8f8b94880f2753ccb796744259da529674e49b9af2e372abf6978c590c0ebfef" url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.1.6" google_sign_in_android: dependency: transitive description: @@ -660,10 +660,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" pool: dependency: transitive description: @@ -676,10 +676,10 @@ packages: dependency: transitive description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "6.0.5" + version: "6.1.1" pub_semver: dependency: transitive description: @@ -873,10 +873,10 @@ packages: dependency: transitive description: name: win32 - sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f" url: "https://pub.dev" source: hosted - version: "5.0.9" + version: "5.1.0" xdg_directories: dependency: transitive description: diff --git a/flutter-ory-network/pubspec.yaml b/flutter-ory-network/pubspec.yaml index 7ef9be76..39934e80 100644 --- a/flutter-ory-network/pubspec.yaml +++ b/flutter-ory-network/pubspec.yaml @@ -34,7 +34,7 @@ dependencies: bloc: ^8.1.2 flutter_bloc: ^8.1.3 dio: ^5.3.2 - ory_client: ^1.1.44 + ory_client: ^1.4.2 flutter_dotenv: ^5.1.0 freezed_annotation: ^2.4.1 json_annotation: ^4.8.1