diff --git a/lib/consts.dart b/lib/consts.dart index 628598e47..dc8ea7be3 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -163,6 +163,27 @@ enum ResponseBodyView { final IconData icon; } +enum AuthType { + noauth("No Auth"), + basic("Basic"), + bearer("Bearer"), + apikey("API Key"), + digest("Digest"), + oauth1("OAuth 1.0"), + oauth2("OAuth 2.0"); + + const AuthType(this.label); + final String label; +} + +enum AddTo { + header("Header"), + query("Query Parameter"); + + const AddTo(this.label); + final String label; +} + const kNoBodyViewOptions = [ResponseBodyView.none]; const kNoRawBodyViewOptions = [ResponseBodyView.none, ResponseBodyView.raw]; const kRawBodyViewOptions = [ResponseBodyView.raw]; @@ -445,6 +466,7 @@ const kLabelURLParams = "URL Params"; const kLabelHeaders = "Headers"; const kLabelBody = "Body"; const kLabelQuery = "Query"; +const kLabelAuthorization = "Authorization"; const kNameCheckbox = "Checkbox"; const kNameURLParam = "URL Parameter"; const kNameHeader = "Header Name"; diff --git a/lib/models/authorization_model.dart b/lib/models/authorization_model.dart new file mode 100644 index 000000000..0a28c4e83 --- /dev/null +++ b/lib/models/authorization_model.dart @@ -0,0 +1,79 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash_core/apidash_core.dart'; + +part 'authorization_model.freezed.dart'; + +part 'authorization_model.g.dart'; + +@freezed +class AuthorizationModel with _$AuthorizationModel { + @JsonSerializable( + explicitToJson: true, + anyMap: true, + ) + const factory AuthorizationModel({ + @Default(AuthType.noauth) AuthType authType, + @Default(BasicAuthModel(username: '', password: '')) BasicAuthModel basicAuthModel, + @Default(BearerAuthModel(token: '')) BearerAuthModel bearerAuthModel, + @Default(ApiKeyAuthModel(key: '', value: '', addTo: AddTo.header)) ApiKeyAuthModel apiKeyAuthModel, + // JWTBearerAuthModel? jwtBearerAuthModel, + // DigestAuthModel? digestAuthModel, + // OAuth1AuthModel? oauth1AuthModel, + // OAuth2AuthModel? oauth2AuthModel, + }) = _AuthorizationModel; + + factory AuthorizationModel.fromJson(Map json) => + _$AuthorizationModelFromJson(json); +} + +@freezed +class BasicAuthModel with _$BasicAuthModel { + @JsonSerializable( + explicitToJson: true, + anyMap: true, + ) + const factory BasicAuthModel({ + @Default("") String username, + @Default("") String password, + }) = _BasicAuthModel; + + factory BasicAuthModel.fromJson(Map json) => + _$BasicAuthModelFromJson(json); +} + +@freezed +class BearerAuthModel with _$BearerAuthModel { + @JsonSerializable( + explicitToJson: true, + anyMap: true, + ) + const factory BearerAuthModel({ + @Default("") String token, + }) = _BearerAuthModel; + + factory BearerAuthModel.fromJson(Map json) => + _$BearerAuthModelFromJson(json); +} + +@freezed +class ApiKeyAuthModel with _$ApiKeyAuthModel { + @JsonSerializable( + explicitToJson: true, + anyMap: true, + ) + const factory ApiKeyAuthModel({ + @Default("") String key, + @Default("") String value, + @Default(AddTo.header) AddTo addTo, + }) = _ApiKeyAuthModel; + + factory ApiKeyAuthModel.fromJson(Map json) => + _$ApiKeyAuthModelFromJson(json); +} + +// @freezed +// class DigestAuthModel with _$DigestAuthModel { +// @JsonSerializable( +// explicitToJson: true, +// anyMap: true, +// ) diff --git a/lib/models/authorization_model.freezed.dart b/lib/models/authorization_model.freezed.dart new file mode 100644 index 000000000..69fe37a6e --- /dev/null +++ b/lib/models/authorization_model.freezed.dart @@ -0,0 +1,795 @@ +// 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 'authorization_model.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#adding-getters-and-methods-to-our-models'); + +AuthorizationModel _$AuthorizationModelFromJson(Map json) { + return _AuthorizationModel.fromJson(json); +} + +/// @nodoc +mixin _$AuthorizationModel { + AuthType get authType => throw _privateConstructorUsedError; + BasicAuthModel get basicAuthModel => throw _privateConstructorUsedError; + BearerAuthModel get bearerAuthModel => throw _privateConstructorUsedError; + ApiKeyAuthModel get apiKeyAuthModel => throw _privateConstructorUsedError; + + /// Serializes this AuthorizationModel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AuthorizationModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthorizationModelCopyWith<$Res> { + factory $AuthorizationModelCopyWith( + AuthorizationModel value, $Res Function(AuthorizationModel) then) = + _$AuthorizationModelCopyWithImpl<$Res, AuthorizationModel>; + @useResult + $Res call( + {AuthType authType, + BasicAuthModel basicAuthModel, + BearerAuthModel bearerAuthModel, + ApiKeyAuthModel apiKeyAuthModel}); + + $BasicAuthModelCopyWith<$Res> get basicAuthModel; + $BearerAuthModelCopyWith<$Res> get bearerAuthModel; + $ApiKeyAuthModelCopyWith<$Res> get apiKeyAuthModel; +} + +/// @nodoc +class _$AuthorizationModelCopyWithImpl<$Res, $Val extends AuthorizationModel> + implements $AuthorizationModelCopyWith<$Res> { + _$AuthorizationModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? authType = null, + Object? basicAuthModel = null, + Object? bearerAuthModel = null, + Object? apiKeyAuthModel = null, + }) { + return _then(_value.copyWith( + authType: null == authType + ? _value.authType + : authType // ignore: cast_nullable_to_non_nullable + as AuthType, + basicAuthModel: null == basicAuthModel + ? _value.basicAuthModel + : basicAuthModel // ignore: cast_nullable_to_non_nullable + as BasicAuthModel, + bearerAuthModel: null == bearerAuthModel + ? _value.bearerAuthModel + : bearerAuthModel // ignore: cast_nullable_to_non_nullable + as BearerAuthModel, + apiKeyAuthModel: null == apiKeyAuthModel + ? _value.apiKeyAuthModel + : apiKeyAuthModel // ignore: cast_nullable_to_non_nullable + as ApiKeyAuthModel, + ) as $Val); + } + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $BasicAuthModelCopyWith<$Res> get basicAuthModel { + return $BasicAuthModelCopyWith<$Res>(_value.basicAuthModel, (value) { + return _then(_value.copyWith(basicAuthModel: value) as $Val); + }); + } + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $BearerAuthModelCopyWith<$Res> get bearerAuthModel { + return $BearerAuthModelCopyWith<$Res>(_value.bearerAuthModel, (value) { + return _then(_value.copyWith(bearerAuthModel: value) as $Val); + }); + } + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiKeyAuthModelCopyWith<$Res> get apiKeyAuthModel { + return $ApiKeyAuthModelCopyWith<$Res>(_value.apiKeyAuthModel, (value) { + return _then(_value.copyWith(apiKeyAuthModel: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$AuthorizationModelImplCopyWith<$Res> + implements $AuthorizationModelCopyWith<$Res> { + factory _$$AuthorizationModelImplCopyWith(_$AuthorizationModelImpl value, + $Res Function(_$AuthorizationModelImpl) then) = + __$$AuthorizationModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {AuthType authType, + BasicAuthModel basicAuthModel, + BearerAuthModel bearerAuthModel, + ApiKeyAuthModel apiKeyAuthModel}); + + @override + $BasicAuthModelCopyWith<$Res> get basicAuthModel; + @override + $BearerAuthModelCopyWith<$Res> get bearerAuthModel; + @override + $ApiKeyAuthModelCopyWith<$Res> get apiKeyAuthModel; +} + +/// @nodoc +class __$$AuthorizationModelImplCopyWithImpl<$Res> + extends _$AuthorizationModelCopyWithImpl<$Res, _$AuthorizationModelImpl> + implements _$$AuthorizationModelImplCopyWith<$Res> { + __$$AuthorizationModelImplCopyWithImpl(_$AuthorizationModelImpl _value, + $Res Function(_$AuthorizationModelImpl) _then) + : super(_value, _then); + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? authType = null, + Object? basicAuthModel = null, + Object? bearerAuthModel = null, + Object? apiKeyAuthModel = null, + }) { + return _then(_$AuthorizationModelImpl( + authType: null == authType + ? _value.authType + : authType // ignore: cast_nullable_to_non_nullable + as AuthType, + basicAuthModel: null == basicAuthModel + ? _value.basicAuthModel + : basicAuthModel // ignore: cast_nullable_to_non_nullable + as BasicAuthModel, + bearerAuthModel: null == bearerAuthModel + ? _value.bearerAuthModel + : bearerAuthModel // ignore: cast_nullable_to_non_nullable + as BearerAuthModel, + apiKeyAuthModel: null == apiKeyAuthModel + ? _value.apiKeyAuthModel + : apiKeyAuthModel // ignore: cast_nullable_to_non_nullable + as ApiKeyAuthModel, + )); + } +} + +/// @nodoc + +@JsonSerializable(explicitToJson: true, anyMap: true) +class _$AuthorizationModelImpl implements _AuthorizationModel { + const _$AuthorizationModelImpl( + {this.authType = AuthType.noauth, + this.basicAuthModel = const BasicAuthModel(username: '', password: ''), + this.bearerAuthModel = const BearerAuthModel(token: ''), + this.apiKeyAuthModel = + const ApiKeyAuthModel(key: '', value: '', addTo: AddTo.header)}); + + factory _$AuthorizationModelImpl.fromJson(Map json) => + _$$AuthorizationModelImplFromJson(json); + + @override + @JsonKey() + final AuthType authType; + @override + @JsonKey() + final BasicAuthModel basicAuthModel; + @override + @JsonKey() + final BearerAuthModel bearerAuthModel; + @override + @JsonKey() + final ApiKeyAuthModel apiKeyAuthModel; + + @override + String toString() { + return 'AuthorizationModel(authType: $authType, basicAuthModel: $basicAuthModel, bearerAuthModel: $bearerAuthModel, apiKeyAuthModel: $apiKeyAuthModel)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AuthorizationModelImpl && + (identical(other.authType, authType) || + other.authType == authType) && + (identical(other.basicAuthModel, basicAuthModel) || + other.basicAuthModel == basicAuthModel) && + (identical(other.bearerAuthModel, bearerAuthModel) || + other.bearerAuthModel == bearerAuthModel) && + (identical(other.apiKeyAuthModel, apiKeyAuthModel) || + other.apiKeyAuthModel == apiKeyAuthModel)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, authType, basicAuthModel, bearerAuthModel, apiKeyAuthModel); + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AuthorizationModelImplCopyWith<_$AuthorizationModelImpl> get copyWith => + __$$AuthorizationModelImplCopyWithImpl<_$AuthorizationModelImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$AuthorizationModelImplToJson( + this, + ); + } +} + +abstract class _AuthorizationModel implements AuthorizationModel { + const factory _AuthorizationModel( + {final AuthType authType, + final BasicAuthModel basicAuthModel, + final BearerAuthModel bearerAuthModel, + final ApiKeyAuthModel apiKeyAuthModel}) = _$AuthorizationModelImpl; + + factory _AuthorizationModel.fromJson(Map json) = + _$AuthorizationModelImpl.fromJson; + + @override + AuthType get authType; + @override + BasicAuthModel get basicAuthModel; + @override + BearerAuthModel get bearerAuthModel; + @override + ApiKeyAuthModel get apiKeyAuthModel; + + /// Create a copy of AuthorizationModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AuthorizationModelImplCopyWith<_$AuthorizationModelImpl> get copyWith => + throw _privateConstructorUsedError; +} + +BasicAuthModel _$BasicAuthModelFromJson(Map json) { + return _BasicAuthModel.fromJson(json); +} + +/// @nodoc +mixin _$BasicAuthModel { + String get username => throw _privateConstructorUsedError; + String get password => throw _privateConstructorUsedError; + + /// Serializes this BasicAuthModel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of BasicAuthModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $BasicAuthModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $BasicAuthModelCopyWith<$Res> { + factory $BasicAuthModelCopyWith( + BasicAuthModel value, $Res Function(BasicAuthModel) then) = + _$BasicAuthModelCopyWithImpl<$Res, BasicAuthModel>; + @useResult + $Res call({String username, String password}); +} + +/// @nodoc +class _$BasicAuthModelCopyWithImpl<$Res, $Val extends BasicAuthModel> + implements $BasicAuthModelCopyWith<$Res> { + _$BasicAuthModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of BasicAuthModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? username = null, + Object? password = null, + }) { + return _then(_value.copyWith( + username: null == username + ? _value.username + : username // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$BasicAuthModelImplCopyWith<$Res> + implements $BasicAuthModelCopyWith<$Res> { + factory _$$BasicAuthModelImplCopyWith(_$BasicAuthModelImpl value, + $Res Function(_$BasicAuthModelImpl) then) = + __$$BasicAuthModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String username, String password}); +} + +/// @nodoc +class __$$BasicAuthModelImplCopyWithImpl<$Res> + extends _$BasicAuthModelCopyWithImpl<$Res, _$BasicAuthModelImpl> + implements _$$BasicAuthModelImplCopyWith<$Res> { + __$$BasicAuthModelImplCopyWithImpl( + _$BasicAuthModelImpl _value, $Res Function(_$BasicAuthModelImpl) _then) + : super(_value, _then); + + /// Create a copy of BasicAuthModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? username = null, + Object? password = null, + }) { + return _then(_$BasicAuthModelImpl( + username: null == username + ? _value.username + : username // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +@JsonSerializable(explicitToJson: true, anyMap: true) +class _$BasicAuthModelImpl implements _BasicAuthModel { + const _$BasicAuthModelImpl({this.username = "", this.password = ""}); + + factory _$BasicAuthModelImpl.fromJson(Map json) => + _$$BasicAuthModelImplFromJson(json); + + @override + @JsonKey() + final String username; + @override + @JsonKey() + final String password; + + @override + String toString() { + return 'BasicAuthModel(username: $username, password: $password)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$BasicAuthModelImpl && + (identical(other.username, username) || + other.username == username) && + (identical(other.password, password) || + other.password == password)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, username, password); + + /// Create a copy of BasicAuthModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$BasicAuthModelImplCopyWith<_$BasicAuthModelImpl> get copyWith => + __$$BasicAuthModelImplCopyWithImpl<_$BasicAuthModelImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$BasicAuthModelImplToJson( + this, + ); + } +} + +abstract class _BasicAuthModel implements BasicAuthModel { + const factory _BasicAuthModel( + {final String username, final String password}) = _$BasicAuthModelImpl; + + factory _BasicAuthModel.fromJson(Map json) = + _$BasicAuthModelImpl.fromJson; + + @override + String get username; + @override + String get password; + + /// Create a copy of BasicAuthModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$BasicAuthModelImplCopyWith<_$BasicAuthModelImpl> get copyWith => + throw _privateConstructorUsedError; +} + +BearerAuthModel _$BearerAuthModelFromJson(Map json) { + return _BearerAuthModel.fromJson(json); +} + +/// @nodoc +mixin _$BearerAuthModel { + String get token => throw _privateConstructorUsedError; + + /// Serializes this BearerAuthModel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of BearerAuthModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $BearerAuthModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $BearerAuthModelCopyWith<$Res> { + factory $BearerAuthModelCopyWith( + BearerAuthModel value, $Res Function(BearerAuthModel) then) = + _$BearerAuthModelCopyWithImpl<$Res, BearerAuthModel>; + @useResult + $Res call({String token}); +} + +/// @nodoc +class _$BearerAuthModelCopyWithImpl<$Res, $Val extends BearerAuthModel> + implements $BearerAuthModelCopyWith<$Res> { + _$BearerAuthModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of BearerAuthModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + }) { + return _then(_value.copyWith( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$BearerAuthModelImplCopyWith<$Res> + implements $BearerAuthModelCopyWith<$Res> { + factory _$$BearerAuthModelImplCopyWith(_$BearerAuthModelImpl value, + $Res Function(_$BearerAuthModelImpl) then) = + __$$BearerAuthModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String token}); +} + +/// @nodoc +class __$$BearerAuthModelImplCopyWithImpl<$Res> + extends _$BearerAuthModelCopyWithImpl<$Res, _$BearerAuthModelImpl> + implements _$$BearerAuthModelImplCopyWith<$Res> { + __$$BearerAuthModelImplCopyWithImpl( + _$BearerAuthModelImpl _value, $Res Function(_$BearerAuthModelImpl) _then) + : super(_value, _then); + + /// Create a copy of BearerAuthModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + }) { + return _then(_$BearerAuthModelImpl( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +@JsonSerializable(explicitToJson: true, anyMap: true) +class _$BearerAuthModelImpl implements _BearerAuthModel { + const _$BearerAuthModelImpl({this.token = ""}); + + factory _$BearerAuthModelImpl.fromJson(Map json) => + _$$BearerAuthModelImplFromJson(json); + + @override + @JsonKey() + final String token; + + @override + String toString() { + return 'BearerAuthModel(token: $token)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$BearerAuthModelImpl && + (identical(other.token, token) || other.token == token)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, token); + + /// Create a copy of BearerAuthModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$BearerAuthModelImplCopyWith<_$BearerAuthModelImpl> get copyWith => + __$$BearerAuthModelImplCopyWithImpl<_$BearerAuthModelImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$BearerAuthModelImplToJson( + this, + ); + } +} + +abstract class _BearerAuthModel implements BearerAuthModel { + const factory _BearerAuthModel({final String token}) = _$BearerAuthModelImpl; + + factory _BearerAuthModel.fromJson(Map json) = + _$BearerAuthModelImpl.fromJson; + + @override + String get token; + + /// Create a copy of BearerAuthModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$BearerAuthModelImplCopyWith<_$BearerAuthModelImpl> get copyWith => + throw _privateConstructorUsedError; +} + +ApiKeyAuthModel _$ApiKeyAuthModelFromJson(Map json) { + return _ApiKeyAuthModel.fromJson(json); +} + +/// @nodoc +mixin _$ApiKeyAuthModel { + String get key => throw _privateConstructorUsedError; + String get value => throw _privateConstructorUsedError; + AddTo get addTo => throw _privateConstructorUsedError; + + /// Serializes this ApiKeyAuthModel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ApiKeyAuthModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ApiKeyAuthModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ApiKeyAuthModelCopyWith<$Res> { + factory $ApiKeyAuthModelCopyWith( + ApiKeyAuthModel value, $Res Function(ApiKeyAuthModel) then) = + _$ApiKeyAuthModelCopyWithImpl<$Res, ApiKeyAuthModel>; + @useResult + $Res call({String key, String value, AddTo addTo}); +} + +/// @nodoc +class _$ApiKeyAuthModelCopyWithImpl<$Res, $Val extends ApiKeyAuthModel> + implements $ApiKeyAuthModelCopyWith<$Res> { + _$ApiKeyAuthModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ApiKeyAuthModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? key = null, + Object? value = null, + Object? addTo = null, + }) { + return _then(_value.copyWith( + key: null == key + ? _value.key + : key // ignore: cast_nullable_to_non_nullable + as String, + value: null == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as String, + addTo: null == addTo + ? _value.addTo + : addTo // ignore: cast_nullable_to_non_nullable + as AddTo, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ApiKeyAuthModelImplCopyWith<$Res> + implements $ApiKeyAuthModelCopyWith<$Res> { + factory _$$ApiKeyAuthModelImplCopyWith(_$ApiKeyAuthModelImpl value, + $Res Function(_$ApiKeyAuthModelImpl) then) = + __$$ApiKeyAuthModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String key, String value, AddTo addTo}); +} + +/// @nodoc +class __$$ApiKeyAuthModelImplCopyWithImpl<$Res> + extends _$ApiKeyAuthModelCopyWithImpl<$Res, _$ApiKeyAuthModelImpl> + implements _$$ApiKeyAuthModelImplCopyWith<$Res> { + __$$ApiKeyAuthModelImplCopyWithImpl( + _$ApiKeyAuthModelImpl _value, $Res Function(_$ApiKeyAuthModelImpl) _then) + : super(_value, _then); + + /// Create a copy of ApiKeyAuthModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? key = null, + Object? value = null, + Object? addTo = null, + }) { + return _then(_$ApiKeyAuthModelImpl( + key: null == key + ? _value.key + : key // ignore: cast_nullable_to_non_nullable + as String, + value: null == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as String, + addTo: null == addTo + ? _value.addTo + : addTo // ignore: cast_nullable_to_non_nullable + as AddTo, + )); + } +} + +/// @nodoc + +@JsonSerializable(explicitToJson: true, anyMap: true) +class _$ApiKeyAuthModelImpl implements _ApiKeyAuthModel { + const _$ApiKeyAuthModelImpl( + {this.key = "", this.value = "", this.addTo = AddTo.header}); + + factory _$ApiKeyAuthModelImpl.fromJson(Map json) => + _$$ApiKeyAuthModelImplFromJson(json); + + @override + @JsonKey() + final String key; + @override + @JsonKey() + final String value; + @override + @JsonKey() + final AddTo addTo; + + @override + String toString() { + return 'ApiKeyAuthModel(key: $key, value: $value, addTo: $addTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ApiKeyAuthModelImpl && + (identical(other.key, key) || other.key == key) && + (identical(other.value, value) || other.value == value) && + (identical(other.addTo, addTo) || other.addTo == addTo)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, key, value, addTo); + + /// Create a copy of ApiKeyAuthModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ApiKeyAuthModelImplCopyWith<_$ApiKeyAuthModelImpl> get copyWith => + __$$ApiKeyAuthModelImplCopyWithImpl<_$ApiKeyAuthModelImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$ApiKeyAuthModelImplToJson( + this, + ); + } +} + +abstract class _ApiKeyAuthModel implements ApiKeyAuthModel { + const factory _ApiKeyAuthModel( + {final String key, + final String value, + final AddTo addTo}) = _$ApiKeyAuthModelImpl; + + factory _ApiKeyAuthModel.fromJson(Map json) = + _$ApiKeyAuthModelImpl.fromJson; + + @override + String get key; + @override + String get value; + @override + AddTo get addTo; + + /// Create a copy of ApiKeyAuthModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ApiKeyAuthModelImplCopyWith<_$ApiKeyAuthModelImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/models/authorization_model.g.dart b/lib/models/authorization_model.g.dart new file mode 100644 index 000000000..6eee10271 --- /dev/null +++ b/lib/models/authorization_model.g.dart @@ -0,0 +1,88 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'authorization_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$AuthorizationModelImpl _$$AuthorizationModelImplFromJson(Map json) => + _$AuthorizationModelImpl( + authType: $enumDecodeNullable(_$AuthTypeEnumMap, json['authType']) ?? + AuthType.noauth, + basicAuthModel: json['basicAuthModel'] == null + ? const BasicAuthModel(username: '', password: '') + : BasicAuthModel.fromJson( + Map.from(json['basicAuthModel'] as Map)), + bearerAuthModel: json['bearerAuthModel'] == null + ? const BearerAuthModel(token: '') + : BearerAuthModel.fromJson( + Map.from(json['bearerAuthModel'] as Map)), + apiKeyAuthModel: json['apiKeyAuthModel'] == null + ? const ApiKeyAuthModel(key: '', value: '', addTo: AddTo.header) + : ApiKeyAuthModel.fromJson( + Map.from(json['apiKeyAuthModel'] as Map)), + ); + +Map _$$AuthorizationModelImplToJson( + _$AuthorizationModelImpl instance) => + { + 'authType': _$AuthTypeEnumMap[instance.authType]!, + 'basicAuthModel': instance.basicAuthModel.toJson(), + 'bearerAuthModel': instance.bearerAuthModel.toJson(), + 'apiKeyAuthModel': instance.apiKeyAuthModel.toJson(), + }; + +const _$AuthTypeEnumMap = { + AuthType.noauth: 'noauth', + AuthType.basic: 'basic', + AuthType.bearer: 'bearer', + AuthType.apikey: 'apikey', + AuthType.digest: 'digest', + AuthType.oauth1: 'oauth1', + AuthType.oauth2: 'oauth2', +}; + +_$BasicAuthModelImpl _$$BasicAuthModelImplFromJson(Map json) => + _$BasicAuthModelImpl( + username: json['username'] as String? ?? "", + password: json['password'] as String? ?? "", + ); + +Map _$$BasicAuthModelImplToJson( + _$BasicAuthModelImpl instance) => + { + 'username': instance.username, + 'password': instance.password, + }; + +_$BearerAuthModelImpl _$$BearerAuthModelImplFromJson(Map json) => + _$BearerAuthModelImpl( + token: json['token'] as String? ?? "", + ); + +Map _$$BearerAuthModelImplToJson( + _$BearerAuthModelImpl instance) => + { + 'token': instance.token, + }; + +_$ApiKeyAuthModelImpl _$$ApiKeyAuthModelImplFromJson(Map json) => + _$ApiKeyAuthModelImpl( + key: json['key'] as String? ?? "", + value: json['value'] as String? ?? "", + addTo: $enumDecodeNullable(_$AddToEnumMap, json['addTo']) ?? AddTo.header, + ); + +Map _$$ApiKeyAuthModelImplToJson( + _$ApiKeyAuthModelImpl instance) => + { + 'key': instance.key, + 'value': instance.value, + 'addTo': _$AddToEnumMap[instance.addTo]!, + }; + +const _$AddToEnumMap = { + AddTo.header: 'header', + AddTo.query: 'query', +}; diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index bb9eefaef..64f220f0c 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,3 +1,4 @@ +import 'package:apidash/models/authorization_model.dart'; import 'package:apidash_core/apidash_core.dart'; part 'request_model.freezed.dart'; @@ -17,6 +18,7 @@ class RequestModel with _$RequestModel { @Default("") String description, @JsonKey(includeToJson: false) @Default(0) requestTabIndex, HttpRequestModel? httpRequestModel, + AuthorizationModel? authorizationModel, int? responseStatus, String? message, HttpResponseModel? httpResponseModel, diff --git a/lib/models/request_model.freezed.dart b/lib/models/request_model.freezed.dart index b237e3726..91598ce2d 100644 --- a/lib/models/request_model.freezed.dart +++ b/lib/models/request_model.freezed.dart @@ -27,6 +27,8 @@ mixin _$RequestModel { @JsonKey(includeToJson: false) dynamic get requestTabIndex => throw _privateConstructorUsedError; HttpRequestModel? get httpRequestModel => throw _privateConstructorUsedError; + AuthorizationModel? get authorizationModel => + throw _privateConstructorUsedError; int? get responseStatus => throw _privateConstructorUsedError; String? get message => throw _privateConstructorUsedError; HttpResponseModel? get httpResponseModel => @@ -59,6 +61,7 @@ abstract class $RequestModelCopyWith<$Res> { String description, @JsonKey(includeToJson: false) dynamic requestTabIndex, HttpRequestModel? httpRequestModel, + AuthorizationModel? authorizationModel, int? responseStatus, String? message, HttpResponseModel? httpResponseModel, @@ -66,6 +69,7 @@ abstract class $RequestModelCopyWith<$Res> { @JsonKey(includeToJson: false) DateTime? sendingTime}); $HttpRequestModelCopyWith<$Res>? get httpRequestModel; + $AuthorizationModelCopyWith<$Res>? get authorizationModel; $HttpResponseModelCopyWith<$Res>? get httpResponseModel; } @@ -90,6 +94,7 @@ class _$RequestModelCopyWithImpl<$Res, $Val extends RequestModel> Object? description = null, Object? requestTabIndex = freezed, Object? httpRequestModel = freezed, + Object? authorizationModel = freezed, Object? responseStatus = freezed, Object? message = freezed, Object? httpResponseModel = freezed, @@ -121,6 +126,10 @@ class _$RequestModelCopyWithImpl<$Res, $Val extends RequestModel> ? _value.httpRequestModel : httpRequestModel // ignore: cast_nullable_to_non_nullable as HttpRequestModel?, + authorizationModel: freezed == authorizationModel + ? _value.authorizationModel + : authorizationModel // ignore: cast_nullable_to_non_nullable + as AuthorizationModel?, responseStatus: freezed == responseStatus ? _value.responseStatus : responseStatus // ignore: cast_nullable_to_non_nullable @@ -158,6 +167,21 @@ class _$RequestModelCopyWithImpl<$Res, $Val extends RequestModel> }); } + /// Create a copy of RequestModel + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $AuthorizationModelCopyWith<$Res>? get authorizationModel { + if (_value.authorizationModel == null) { + return null; + } + + return $AuthorizationModelCopyWith<$Res>(_value.authorizationModel!, + (value) { + return _then(_value.copyWith(authorizationModel: value) as $Val); + }); + } + /// Create a copy of RequestModel /// with the given fields replaced by the non-null parameter values. @override @@ -188,6 +212,7 @@ abstract class _$$RequestModelImplCopyWith<$Res> String description, @JsonKey(includeToJson: false) dynamic requestTabIndex, HttpRequestModel? httpRequestModel, + AuthorizationModel? authorizationModel, int? responseStatus, String? message, HttpResponseModel? httpResponseModel, @@ -197,6 +222,8 @@ abstract class _$$RequestModelImplCopyWith<$Res> @override $HttpRequestModelCopyWith<$Res>? get httpRequestModel; @override + $AuthorizationModelCopyWith<$Res>? get authorizationModel; + @override $HttpResponseModelCopyWith<$Res>? get httpResponseModel; } @@ -219,6 +246,7 @@ class __$$RequestModelImplCopyWithImpl<$Res> Object? description = null, Object? requestTabIndex = freezed, Object? httpRequestModel = freezed, + Object? authorizationModel = freezed, Object? responseStatus = freezed, Object? message = freezed, Object? httpResponseModel = freezed, @@ -249,6 +277,10 @@ class __$$RequestModelImplCopyWithImpl<$Res> ? _value.httpRequestModel : httpRequestModel // ignore: cast_nullable_to_non_nullable as HttpRequestModel?, + authorizationModel: freezed == authorizationModel + ? _value.authorizationModel + : authorizationModel // ignore: cast_nullable_to_non_nullable + as AuthorizationModel?, responseStatus: freezed == responseStatus ? _value.responseStatus : responseStatus // ignore: cast_nullable_to_non_nullable @@ -284,6 +316,7 @@ class _$RequestModelImpl implements _RequestModel { this.description = "", @JsonKey(includeToJson: false) this.requestTabIndex = 0, this.httpRequestModel, + this.authorizationModel, this.responseStatus, this.message, this.httpResponseModel, @@ -310,6 +343,8 @@ class _$RequestModelImpl implements _RequestModel { @override final HttpRequestModel? httpRequestModel; @override + final AuthorizationModel? authorizationModel; + @override final int? responseStatus; @override final String? message; @@ -324,7 +359,7 @@ class _$RequestModelImpl implements _RequestModel { @override String toString() { - return 'RequestModel(id: $id, apiType: $apiType, name: $name, description: $description, requestTabIndex: $requestTabIndex, httpRequestModel: $httpRequestModel, responseStatus: $responseStatus, message: $message, httpResponseModel: $httpResponseModel, isWorking: $isWorking, sendingTime: $sendingTime)'; + return 'RequestModel(id: $id, apiType: $apiType, name: $name, description: $description, requestTabIndex: $requestTabIndex, httpRequestModel: $httpRequestModel, authorizationModel: $authorizationModel, responseStatus: $responseStatus, message: $message, httpResponseModel: $httpResponseModel, isWorking: $isWorking, sendingTime: $sendingTime)'; } @override @@ -341,6 +376,8 @@ class _$RequestModelImpl implements _RequestModel { .equals(other.requestTabIndex, requestTabIndex) && (identical(other.httpRequestModel, httpRequestModel) || other.httpRequestModel == httpRequestModel) && + (identical(other.authorizationModel, authorizationModel) || + other.authorizationModel == authorizationModel) && (identical(other.responseStatus, responseStatus) || other.responseStatus == responseStatus) && (identical(other.message, message) || other.message == message) && @@ -362,6 +399,7 @@ class _$RequestModelImpl implements _RequestModel { description, const DeepCollectionEquality().hash(requestTabIndex), httpRequestModel, + authorizationModel, responseStatus, message, httpResponseModel, @@ -392,6 +430,7 @@ abstract class _RequestModel implements RequestModel { final String description, @JsonKey(includeToJson: false) final dynamic requestTabIndex, final HttpRequestModel? httpRequestModel, + final AuthorizationModel? authorizationModel, final int? responseStatus, final String? message, final HttpResponseModel? httpResponseModel, @@ -416,6 +455,8 @@ abstract class _RequestModel implements RequestModel { @override HttpRequestModel? get httpRequestModel; @override + AuthorizationModel? get authorizationModel; + @override int? get responseStatus; @override String? get message; diff --git a/lib/models/request_model.g.dart b/lib/models/request_model.g.dart index 68b563953..a2dc6d6b6 100644 --- a/lib/models/request_model.g.dart +++ b/lib/models/request_model.g.dart @@ -17,6 +17,10 @@ _$RequestModelImpl _$$RequestModelImplFromJson(Map json) => _$RequestModelImpl( ? null : HttpRequestModel.fromJson( Map.from(json['httpRequestModel'] as Map)), + authorizationModel: json['authorizationModel'] == null + ? null + : AuthorizationModel.fromJson( + Map.from(json['authorizationModel'] as Map)), responseStatus: (json['responseStatus'] as num?)?.toInt(), message: json['message'] as String?, httpResponseModel: json['httpResponseModel'] == null @@ -36,6 +40,7 @@ Map _$$RequestModelImplToJson(_$RequestModelImpl instance) => 'name': instance.name, 'description': instance.description, 'httpRequestModel': instance.httpRequestModel?.toJson(), + 'authorizationModel': instance.authorizationModel?.toJson(), 'responseStatus': instance.responseStatus, 'message': instance.message, 'httpResponseModel': instance.httpResponseModel?.toJson(), diff --git a/lib/providers/authorization_providers.dart b/lib/providers/authorization_providers.dart new file mode 100644 index 000000000..f7c21685a --- /dev/null +++ b/lib/providers/authorization_providers.dart @@ -0,0 +1,59 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash/providers/collection_providers.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:apidash/models/authorization_model.dart'; + +class AuthorizationNotifier extends StateNotifier { + final Ref ref; + + AuthorizationNotifier(AuthorizationModel initialState, this.ref) + : super(initialState); + + void update({ + AuthType? authType, + String? username, + String? password, + String? token, + String? apiKey, + String? apiValue, + AddTo? addTo, + }) { + if (authType != null && authType != state.authType) { + state = state.copyWith(authType: authType); + } + // General state update + state = state.copyWith( + basicAuthModel: state.authType == AuthType.basic + ? state.basicAuthModel.copyWith( + username: username ?? state.basicAuthModel.username, + password: password ?? state.basicAuthModel.password, + ) + : state.basicAuthModel, + bearerAuthModel: state.authType == AuthType.bearer + ? state.bearerAuthModel.copyWith( + token: token ?? state.bearerAuthModel.token, + ) : state.bearerAuthModel, + apiKeyAuthModel: state.authType == AuthType.apikey + ? state.apiKeyAuthModel.copyWith( + key: apiKey ?? state.apiKeyAuthModel.key, + value: apiValue ?? state.apiKeyAuthModel.value, + addTo: addTo ?? state.apiKeyAuthModel.addTo, + ) : state.apiKeyAuthModel, + ); + + _syncWithRequest(); + } + + void _syncWithRequest() { + ref.read(collectionStateNotifierProvider.notifier).update( + authorizationModel: state, + ); + } +} + +final authorizationProvider = + StateNotifierProvider((ref) { + final currentRequest = ref.watch(selectedRequestModelProvider); + return AuthorizationNotifier( + currentRequest?.authorizationModel ?? AuthorizationModel(), ref); +}); diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 35bc4aa0c..4ed974d5d 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,3 +1,4 @@ +import 'package:apidash/models/authorization_model.dart'; import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -25,6 +26,7 @@ final requestSequenceProvider = StateProvider>((ref) { return ids ?? []; }); +/// TODO: Provider for current request model final StateNotifierProvider?> collectionStateNotifierProvider = StateNotifierProvider((ref) => CollectionStateNotifier( @@ -204,10 +206,12 @@ class CollectionStateNotifier unsave(); } + /// TODO: Update the request model with given parameters for each change void update({ String? id, HTTPVerb? method, APIType? apiType, + AuthorizationModel? authorizationModel, String? url, String? name, String? description, @@ -233,6 +237,7 @@ class CollectionStateNotifier var currentHttpRequestModel = currentModel.httpRequestModel; final newModel = currentModel.copyWith( apiType: apiType ?? currentModel.apiType, + authorizationModel: authorizationModel ?? currentModel.authorizationModel, name: name ?? currentModel.name, description: description ?? currentModel.description, requestTabIndex: requestTabIndex ?? currentModel.requestTabIndex, @@ -262,6 +267,7 @@ class CollectionStateNotifier unsave(); } + /// TODO: Send the request with all given parameters Future sendRequest() async { final requestId = ref.read(selectedIdStateProvider); ref.read(codePaneVisibleStateProvider.notifier).state = false; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_authorization.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_authorization.dart new file mode 100644 index 000000000..fe647550b --- /dev/null +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_authorization.dart @@ -0,0 +1,358 @@ +import 'dart:convert'; +import 'dart:math'; +import 'package:apidash/providers/authorization_providers.dart'; +import 'package:apidash/providers/collection_providers.dart'; +import 'package:apidash_core/apidash_core.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; +import 'package:apidash/consts.dart'; + +class EditRequestAuthorization extends ConsumerStatefulWidget { + const EditRequestAuthorization({super.key}); + + @override + ConsumerState createState() => + _EditRequestAuthorizationState(); +} + +class _EditRequestAuthorizationState + extends ConsumerState { + late int seed; + final random = Random.secure(); + bool _obscurePassword = true; + + @override + void initState() { + super.initState(); + seed = random.nextInt(kRandMax); + } + + void _updateHeaders() { + final currentHeaders = + ref.read(selectedRequestModelProvider)?.httpRequestModel?.headers ?? []; + final authModel = ref.watch(authorizationProvider); + final currentAuthType = + ref.watch(authorizationProvider.select((value) => value.authType)); + var newHeaders = currentHeaders.toList(); + + if (currentAuthType == AuthType.basic || + currentAuthType == AuthType.bearer) { + newHeaders = currentHeaders + .where((h) => (h.name).toLowerCase() != 'authorization') + .toList(); + } + if (currentAuthType == AuthType.apikey && + authModel.apiKeyAuthModel.addTo == AddTo.header) { + if (authModel.apiKeyAuthModel.key.isNotEmpty && + authModel.apiKeyAuthModel.value.isNotEmpty) { + newHeaders.add(NameValueModel( + name: authModel.apiKeyAuthModel.key, + value: authModel.apiKeyAuthModel.value, + )); + } + } + + if (currentAuthType != AuthType.noauth) { + String authValue = ''; + switch (currentAuthType) { + case AuthType.basic: + authValue = + 'Basic ${base64Encode(utf8.encode('${authModel.basicAuthModel.username}:${authModel.basicAuthModel.password}'))}'; + break; + case AuthType.bearer: + authValue = 'Bearer ${authModel.bearerAuthModel.token}'; + break; + case AuthType.noauth: + break; + default: + break; + } + + if (authValue.isNotEmpty) { + newHeaders.add(NameValueModel( + name: 'Authorization', + value: authValue, + )); + } + } + + ref.read(collectionStateNotifierProvider.notifier).update( + headers: newHeaders, + isHeaderEnabledList: List.filled(newHeaders.length, true), + ); + } + +void _updateQueryParams() { + final currentParams = ref + .read(selectedRequestModelProvider) + ?.httpRequestModel + ?.params ?? + []; + final authModel = ref.watch(authorizationProvider); + final currentAuthType = + ref.watch(authorizationProvider.select((value) => value.authType)); + + if ( + currentAuthType == AuthType.apikey && + authModel.apiKeyAuthModel.addTo == AddTo.query) { + final apiKeyName = authModel.apiKeyAuthModel.key; + final apiKeyvalue = authModel.apiKeyAuthModel.value; + + if (apiKeyName.isNotEmpty && apiKeyvalue.isNotEmpty) { + // Check if a parameter with ANY name from apiKey auth already exists + // if it does, we need to update the name and value + // if it doesn't, we need to add a new parameter + bool foundExisting = false; + List newParams = currentParams.map((param) { + if (currentParams.indexWhere((p) => p.name == authModel.apiKeyAuthModel.key) != -1) { + foundExisting = true; + return param.copyWith(name: apiKeyName, value: apiKeyvalue); + } + return param; + }).toList(); + + if (!foundExisting) { + // Add new parameter + newParams = [...newParams, NameValueModel(name: apiKeyName, value: apiKeyvalue)]; + } + + ref.read(collectionStateNotifierProvider.notifier).update( + params: newParams, + isParamEnabledList: List.filled(newParams.length, true), + ); + } + } else { + //If not enabled or not apiKey auth, remove the param if it exists + List newParams = currentParams.where((param) => param.name != authModel.apiKeyAuthModel.key).toList(); + ref.read(collectionStateNotifierProvider.notifier).update( + params: newParams, + isParamEnabledList: List.filled(newParams.length, true), + ); + } +} + + // @override + // void didUpdateWidget(covariant EditRequestAuthorization oldWidget) { + // super.didUpdateWidget(oldWidget); + // _updateHeaders(); + // _updateQueryParams(); + + // } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final colorScheme = theme.colorScheme; + + final authNotifier = ref.read(authorizationProvider.notifier); + final authModel = ref.watch(authorizationProvider); + final currentAuthType = + ref.watch(authorizationProvider.select((value) => value.authType)); + final selectedId = ref.watch(selectedIdStateProvider); + + return Padding( + padding: kP10, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'The authorization header will be automatically generated when you send the request.'), + const SizedBox(height: 16), + ...[ + SizedBox( + height: kHeaderHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text("Select Authorization Type:"), + const SizedBox(width: 8), + ADDropdownButton( + value: currentAuthType, + values: [ + (AuthType.noauth, 'No Auth'), + (AuthType.basic, 'Basic Auth'), + (AuthType.bearer, 'Bearer Token'), + (AuthType.apikey, 'API Key'), + ], + onChanged: (value) { + authNotifier.update( + authType: value, + ); + }, + ), + ], + ), + ), + const SizedBox(height: 16), + switch (currentAuthType) { + AuthType.basic => Column(children: [ + TextFormField( + key: Key("$selectedId-username"), + decoration: InputDecoration( + labelText: 'Username', + contentPadding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8)), + filled: true, + fillColor: colorScheme.surface, + ), + initialValue: authModel.basicAuthModel.username, + onChanged: (value) { + authNotifier.update( + username: value, + ); + + /// TODO: when value is not null and not empty add the authorization header + if (value.isNotEmpty) { + _updateHeaders(); + } + }, + ), + const SizedBox(height: 12), + TextFormField( + key: Key("$selectedId-password"), + decoration: InputDecoration( + labelText: 'Password', + contentPadding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8)), + filled: true, + fillColor: colorScheme.surface, + suffixIcon: IconButton( + icon: Icon( + _obscurePassword + ? Icons.visibility_off + : Icons.visibility, + color: colorScheme.onSurface.withAlpha(150), + ), + onPressed: () { + setState(() { + _obscurePassword = !_obscurePassword; + }); + }, + ), + ), + initialValue: authModel.basicAuthModel.password, + obscureText: _obscurePassword, + onChanged: (value) { + authNotifier.update( + password: value, + ); + if (value.isNotEmpty) { + _updateHeaders(); + } + }, + ), + ]), + AuthType.bearer => Column(children: [ + TextFormField( + key: Key("$selectedId-token"), + decoration: InputDecoration( + labelText: 'Token', + contentPadding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8)), + filled: true, + fillColor: colorScheme.surface, + ), + initialValue: authModel.bearerAuthModel.token, + onChanged: (value) { + authNotifier.update( + token: value, + ); + if (value.isNotEmpty) { + _updateHeaders(); + } + }, + ), + ]), + AuthType.apikey => Column(children: [ + TextFormField( + key: Key("$selectedId-key"), + decoration: InputDecoration( + labelText: 'Key', + contentPadding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8)), + filled: true, + fillColor: colorScheme.surface, + ), + initialValue: authModel.apiKeyAuthModel.key, + onChanged: (value) { + authNotifier.update( + apiKey: value, + ); + if (value.isNotEmpty && + authModel.apiKeyAuthModel.addTo == AddTo.query) { + _updateQueryParams(); + } + }, + ), + const SizedBox(height: 12), + TextFormField( + key: Key("$selectedId-value"), + decoration: InputDecoration( + labelText: 'Value', + contentPadding: const EdgeInsets.symmetric( + vertical: 12, horizontal: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8)), + filled: true, + fillColor: colorScheme.surface, + ), + initialValue: authModel.apiKeyAuthModel.value, + onChanged: (value) { + authNotifier.update( + apiValue: value, + ); + if (value.isNotEmpty && + authModel.apiKeyAuthModel.addTo == AddTo.query) { + _updateQueryParams(); + } + }, + ), + const SizedBox(height: 12), + SizedBox( + height: kHeaderHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text("Add to:"), + const SizedBox(width: 8), + ADDropdownButton( + value: authModel.apiKeyAuthModel.addTo, + values: [ + ( + AddTo.header, + 'Header', + ), + (AddTo.query, 'Query Params'), + ], + onChanged: (value) { + authNotifier.update( + addTo: value, + ); + if (value == AddTo.header) { + _updateHeaders(); + } else if (value == AddTo.query) { + _updateQueryParams(); + } + }, + ), + ], + ), + ), + ]), + _ => Container() + }, + ], + ], + ), + ); + } +} diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 658789a09..82c348e3f 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -28,6 +28,8 @@ class EditRequestHeadersState extends ConsumerState { seed = random.nextInt(kRandMax); } + + /// TODO: When the field is changed, we update the headers and isHeaderEnabledList void _onFieldChange() { ref.read(collectionStateNotifierProvider.notifier).update( headers: headerRows.sublist(0, headerRows.length - 1), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane_rest.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane_rest.dart index e323f83b8..d5e887156 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane_rest.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane_rest.dart @@ -1,4 +1,5 @@ import 'package:apidash/consts.dart'; +import 'package:apidash/screens/home_page/editor_pane/details_card/request_pane/request_authorization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; @@ -17,6 +18,8 @@ class EditRestRequestPane extends ConsumerWidget { final tabIndex = ref.watch( selectedRequestModelProvider.select((value) => value?.requestTabIndex)); + final authType = ref.watch(selectedRequestModelProvider.select((value) => value?.authorizationModel?.authType)); + final headerLength = ref.watch(selectedRequestModelProvider .select((value) => value?.httpRequestModel?.headersMap.length)) ?? 0; @@ -43,16 +46,19 @@ class EditRestRequestPane extends ConsumerWidget { showIndicators: [ paramLength > 0, headerLength > 0, + authType != AuthType.noauth, hasBody, ], tabLabels: const [ kLabelURLParams, kLabelHeaders, + kLabelAuthorization, kLabelBody, ], children: const [ EditRequestURLParams(), EditRequestHeaders(), + EditRequestAuthorization(), EditRequestBody(), ], ); diff --git a/lib/widgets/dropdown_auth_type.dart b/lib/widgets/dropdown_auth_type.dart new file mode 100644 index 000000000..c094e2289 --- /dev/null +++ b/lib/widgets/dropdown_auth_type.dart @@ -0,0 +1,24 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash_design_system/apidash_design_system.dart'; +import 'package:flutter/material.dart'; + +class DropdownButtonAuthType extends StatelessWidget { + const DropdownButtonAuthType({ + super.key, + this.authType, + this.onChanged, + }); + + final AuthType? authType; + final void Function(AuthType?)? onChanged; + + @override + Widget build(BuildContext context) { + return ADDropdownButton( + value: authType, + values: AuthType.values.map((e) => (e, e.name)), + onChanged: onChanged, + iconSize: 16, + ); + } +} diff --git a/lib/widgets/request_pane.dart b/lib/widgets/request_pane.dart index 48535bf41..084ad922a 100644 --- a/lib/widgets/request_pane.dart +++ b/lib/widgets/request_pane.dart @@ -4,6 +4,8 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:apidash/consts.dart'; import 'tab_label.dart'; +/// TODO: For setting a new tab + class RequestPane extends StatefulHookWidget { const RequestPane({ super.key, @@ -14,7 +16,7 @@ class RequestPane extends StatefulHookWidget { this.onTapTabBar, required this.tabLabels, required this.children, - this.showIndicators = const [false, false, false], + this.showIndicators = const [false, false, false, false], this.showViewCodeButton, }); diff --git a/packages/apidash_core/lib/consts.dart b/packages/apidash_core/lib/consts.dart index c1d45ad42..f0bd76f25 100644 --- a/packages/apidash_core/lib/consts.dart +++ b/packages/apidash_core/lib/consts.dart @@ -86,6 +86,8 @@ enum ContentType { final String header; } + + const JsonEncoder kJsonEncoder = JsonEncoder.withIndent(' '); const JsonDecoder kJsonDecoder = JsonDecoder(); const LineSplitter kSplitter = LineSplitter(); diff --git a/packages/multi_trigger_autocomplete_plus/example/lib/main.dart b/packages/multi_trigger_autocomplete_plus/example/lib/main.dart index 821ad2955..79111410e 100644 --- a/packages/multi_trigger_autocomplete_plus/example/lib/main.dart +++ b/packages/multi_trigger_autocomplete_plus/example/lib/main.dart @@ -9,7 +9,7 @@ import 'package:multi_trigger_autocomplete_plus/multi_trigger_autocomplete_plus. void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); + const MyApp({super.key}); // This widget is the root of your application. @override @@ -30,7 +30,7 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - const MyHomePage({Key? key}) : super(key: key); + const MyHomePage({super.key}); @override State createState() => _MyHomePageState(); diff --git a/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_list.dart b/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_list.dart index 99dea84fc..69b14bf5d 100644 --- a/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_list.dart +++ b/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_list.dart @@ -5,9 +5,9 @@ import 'package:google_fonts/google_fonts.dart'; class ChatMessageList extends StatelessWidget { const ChatMessageList({ - Key? key, + super.key, required this.messages, - }) : super(key: key); + }); final List messages; diff --git a/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_text_field.dart b/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_text_field.dart index 5f9d85e94..a004c3574 100644 --- a/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_text_field.dart +++ b/packages/multi_trigger_autocomplete_plus/example/lib/src/chat_message_text_field.dart @@ -6,11 +6,11 @@ import 'package:example/src/data.dart'; class ChatMessageTextField extends StatelessWidget { const ChatMessageTextField({ - Key? key, + super.key, required this.focusNode, required this.controller, required this.onSend, - }) : super(key: key); + }); final FocusNode focusNode; final TextEditingController controller; diff --git a/packages/multi_trigger_autocomplete_plus/example/lib/src/options/emoji_autocomplete_options.dart b/packages/multi_trigger_autocomplete_plus/example/lib/src/options/emoji_autocomplete_options.dart index d987f451c..e7cfbdc3a 100644 --- a/packages/multi_trigger_autocomplete_plus/example/lib/src/options/emoji_autocomplete_options.dart +++ b/packages/multi_trigger_autocomplete_plus/example/lib/src/options/emoji_autocomplete_options.dart @@ -5,10 +5,10 @@ import 'package:example/src/models.dart'; class EmojiAutocompleteOptions extends StatelessWidget { const EmojiAutocompleteOptions({ - Key? key, + super.key, required this.query, required this.onEmojiTap, - }) : super(key: key); + }); final String query; final ValueSetter onEmojiTap; diff --git a/packages/multi_trigger_autocomplete_plus/example/lib/src/options/hashtag_autocomplete_options.dart b/packages/multi_trigger_autocomplete_plus/example/lib/src/options/hashtag_autocomplete_options.dart index 791bd6ba6..3d071f835 100644 --- a/packages/multi_trigger_autocomplete_plus/example/lib/src/options/hashtag_autocomplete_options.dart +++ b/packages/multi_trigger_autocomplete_plus/example/lib/src/options/hashtag_autocomplete_options.dart @@ -5,10 +5,10 @@ import 'package:example/src/models.dart'; class HashtagAutocompleteOptions extends StatelessWidget { const HashtagAutocompleteOptions({ - Key? key, + super.key, required this.query, required this.onHashtagTap, - }) : super(key: key); + }); final String query; final ValueSetter onHashtagTap; diff --git a/packages/multi_trigger_autocomplete_plus/example/lib/src/options/mention_autocomplete_options.dart b/packages/multi_trigger_autocomplete_plus/example/lib/src/options/mention_autocomplete_options.dart index 5df2b2786..08864769a 100644 --- a/packages/multi_trigger_autocomplete_plus/example/lib/src/options/mention_autocomplete_options.dart +++ b/packages/multi_trigger_autocomplete_plus/example/lib/src/options/mention_autocomplete_options.dart @@ -5,10 +5,10 @@ import 'package:example/src/models.dart'; class MentionAutocompleteOptions extends StatelessWidget { const MentionAutocompleteOptions({ - Key? key, + super.key, required this.query, required this.onMentionUserTap, - }) : super(key: key); + }); final String query; final ValueSetter onMentionUserTap; diff --git a/packages/multi_trigger_autocomplete_plus/example/pubspec.lock b/packages/multi_trigger_autocomplete_plus/example/pubspec.lock index 5bfc05a8b..490d95a1e 100644 --- a/packages/multi_trigger_autocomplete_plus/example/pubspec.lock +++ b/packages/multi_trigger_autocomplete_plus/example/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" flutter: dependency: "direct main" description: flutter @@ -127,10 +127,10 @@ packages: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.2" leak_tracker: dependency: transitive description: @@ -347,10 +347,10 @@ packages: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" xdg_directories: dependency: transitive description: @@ -360,5 +360,5 @@ packages: source: hosted version: "1.1.0" sdks: - dart: ">=3.7.0-0 <4.0.0" + dart: ">=3.7.0 <4.0.0" flutter: ">=3.24.0" diff --git a/packages/multi_trigger_autocomplete_plus/lib/src/multi_trigger_autocomplete.dart b/packages/multi_trigger_autocomplete_plus/lib/src/multi_trigger_autocomplete.dart index 2bb54313e..fd0a3cf2a 100644 --- a/packages/multi_trigger_autocomplete_plus/lib/src/multi_trigger_autocomplete.dart +++ b/packages/multi_trigger_autocomplete_plus/lib/src/multi_trigger_autocomplete.dart @@ -466,10 +466,9 @@ class _AutocompleteInvokedTriggerWithQuery { // The default Material-style Autocomplete text field. class _MultiTriggerAutocompleteField extends StatelessWidget { const _MultiTriggerAutocompleteField({ - Key? key, required this.focusNode, required this.textEditingController, - }) : super(key: key); + }); final FocusNode focusNode; diff --git a/packages/multi_trigger_autocomplete_plus/test/multi_trigger_autocomplete_test.dart b/packages/multi_trigger_autocomplete_plus/test/multi_trigger_autocomplete_test.dart index aa52e07c9..17874fc35 100644 --- a/packages/multi_trigger_autocomplete_plus/test/multi_trigger_autocomplete_test.dart +++ b/packages/multi_trigger_autocomplete_plus/test/multi_trigger_autocomplete_test.dart @@ -310,7 +310,7 @@ class User { } class Boilerplate extends StatelessWidget { - const Boilerplate({Key? key, this.child}) : super(key: key); + const Boilerplate({super.key, this.child}); final Widget? child;