diff --git a/lib/screens/common_widgets/auth/api_key_auth_fields.dart b/lib/screens/common_widgets/auth/api_key_auth_fields.dart new file mode 100644 index 00000000..ab4370be --- /dev/null +++ b/lib/screens/common_widgets/auth/api_key_auth_fields.dart @@ -0,0 +1,141 @@ +import 'package:apidash_core/consts.dart'; +import 'package:apidash_core/models/auth/api_auth_model.dart'; +import 'package:apidash_core/models/auth/auth_api_key_model.dart'; +import 'package:flutter/material.dart'; + +class ApiKeyAuthFields extends StatefulWidget { + final AuthModel? authData; + final Function(AuthModel?) updateAuth; + + const ApiKeyAuthFields({ + super.key, + required this.authData, + required this.updateAuth, + }); + + @override + State createState() => _ApiKeyAuthFieldsState(); +} + +class _ApiKeyAuthFieldsState extends State { + late TextEditingController _keyController; + late TextEditingController _nameController; + late String _addKeyTo; + + @override + void initState() { + super.initState(); + final apiAuth = widget.authData?.apikey; + _keyController = TextEditingController(text: apiAuth?.key ?? ''); + _nameController = TextEditingController(text: apiAuth?.name ?? ''); + _addKeyTo = apiAuth?.location ?? 'header'; + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Add to", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + height: 4, + ), + DropdownButtonFormField( + value: _addKeyTo, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + items: [ + DropdownMenuItem( + value: 'header', + child: Text('Header'), + ), + DropdownMenuItem( + value: 'query', + child: Text('Query Params'), + ), + ], + onChanged: (String? newLocation) { + if (newLocation != null) { + _updateApiKeyAuth(); + } + }, + ), + const SizedBox(height: 16), + Text( + "Header/Query Param Name", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + height: 4, + ), + TextField( + controller: _nameController, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + hintText: "Header/Query Param Name", + hintStyle: Theme.of(context).textTheme.bodyMedium, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + onChanged: (value) => _updateApiKeyAuth(), + ), + const SizedBox(height: 16), + Text( + "API Key", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + height: 4, + ), + TextField( + controller: _keyController, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + hintText: "API Key", + hintStyle: Theme.of(context).textTheme.bodyMedium, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + onChanged: (value) => _updateApiKeyAuth(), + ), + ], + ); + } + + void _updateApiKeyAuth() { + widget.updateAuth( + widget.authData?.copyWith( + type: APIAuthType.apiKey, + apikey: AuthApiKeyModel( + key: _keyController.text.trim(), + name: _nameController.text.trim(), + location: _addKeyTo, + ), + ), + ); + } +} diff --git a/lib/screens/common_widgets/auth/basic_auth_fields.dart b/lib/screens/common_widgets/auth/basic_auth_fields.dart new file mode 100644 index 00000000..0ac0b6c6 --- /dev/null +++ b/lib/screens/common_widgets/auth/basic_auth_fields.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:apidash_core/apidash_core.dart'; + +class BasicAuthFields extends StatelessWidget { + final AuthModel? authData; + final Function(AuthModel?) updateAuth; + + const BasicAuthFields({ + super.key, + required this.authData, + required this.updateAuth, + }); + + @override + Widget build(BuildContext context) { + final usernameController = TextEditingController( + text: authData?.basic?.username ?? '', + ); + final passwordController = TextEditingController( + text: authData?.basic?.password ?? '', + ); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Username", + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 4), + TextField( + controller: usernameController, + decoration: _inputDecoration(context, "Username"), + onChanged: (_) => _updateBasicAuth( + usernameController, + passwordController, + ), + ), + const SizedBox(height: 16), + Text( + "Password", + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 4), + TextField( + controller: passwordController, + decoration: _inputDecoration(context, "Password"), + obscureText: true, + onChanged: (_) => _updateBasicAuth( + usernameController, + passwordController, + ), + ), + ], + ); + } + + InputDecoration _inputDecoration(BuildContext context, String hint) { + return InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + hintText: hint, + hintStyle: Theme.of(context).textTheme.bodyMedium, + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), + ); + } + + void _updateBasicAuth( + TextEditingController usernameController, + TextEditingController passwordController, + ) { + updateAuth( + authData?.copyWith( + type: APIAuthType.basic, + basic: AuthBasicAuthModel( + username: usernameController.text.trim(), + password: passwordController.text.trim(), + ), + ), + ); + } +} diff --git a/lib/screens/common_widgets/auth/bearer_auth_fields.dart b/lib/screens/common_widgets/auth/bearer_auth_fields.dart new file mode 100644 index 00000000..47b4f738 --- /dev/null +++ b/lib/screens/common_widgets/auth/bearer_auth_fields.dart @@ -0,0 +1,71 @@ +import 'package:apidash_core/apidash_core.dart'; +import 'package:flutter/material.dart'; + +class BearerAuthFields extends StatefulWidget { + final AuthModel? authData; + final Function(AuthModel?) updateAuth; + + const BearerAuthFields({ + super.key, + required this.authData, + required this.updateAuth, + }); + + @override + State createState() => _BearerAuthFieldsState(); +} + +class _BearerAuthFieldsState extends State { + late TextEditingController _tokenController; + + @override + void initState() { + super.initState(); + final bearerAuth = widget.authData?.bearer; + _tokenController = TextEditingController(text: bearerAuth?.token ?? ''); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Token", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + height: 4, + ), + TextField( + controller: _tokenController, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + hintText: "Token", + hintStyle: Theme.of(context).textTheme.bodyMedium, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + onChanged: (value) => _updateBearerAuth(), + ), + ], + ); + } + + void _updateBearerAuth() { + widget.updateAuth( + widget.authData?.copyWith( + type: APIAuthType.bearer, + bearer: AuthBearerModel( + token: _tokenController.text.trim(), + ), + ), + ); + } +} diff --git a/lib/screens/common_widgets/auth/jwt_auth_fields.dart b/lib/screens/common_widgets/auth/jwt_auth_fields.dart new file mode 100644 index 00000000..a64d9820 --- /dev/null +++ b/lib/screens/common_widgets/auth/jwt_auth_fields.dart @@ -0,0 +1,307 @@ +import 'package:flutter/material.dart'; +import 'package:apidash_core/apidash_core.dart'; + +class JwtAuthFields extends StatefulWidget { + final AuthModel? authData; + final Function(AuthModel?) updateAuth; + + const JwtAuthFields({ + super.key, + required this.authData, + required this.updateAuth, + }); + + @override + State createState() => _JwtAuthFieldsState(); +} + +class _JwtAuthFieldsState extends State { + late TextEditingController _secretController; + late TextEditingController _payloadController; + late String _addTokenTo; + late String _algorithm; + late bool _isSecretBase64Encoded; + + @override + void initState() { + super.initState(); + final jwt = widget.authData?.jwt; + _secretController = TextEditingController(text: jwt?.secret ?? ''); + _payloadController = TextEditingController(text: jwt?.payload ?? ''); + _addTokenTo = jwt?.addTokenTo ?? 'header'; + _algorithm = jwt?.algorithm ?? 'HS256'; + _isSecretBase64Encoded = jwt?.isSecretBase64Encoded ?? false; + } + + @override + Widget build(BuildContext context) { + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Add JWT token to", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 4), + DropdownButtonFormField( + value: _addTokenTo, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + items: [ + DropdownMenuItem( + value: 'header', + child: Text('Request Header'), + ), + DropdownMenuItem( + value: 'query', + child: Text('Query Parameters'), + ), + ], + onChanged: (String? newAddTokenTo) { + if (newAddTokenTo != null) { + _updateJwtAuth(); + } + }, + ), + const SizedBox(height: 16), + Text( + "Algorithm", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 4), + DropdownButtonFormField( + value: _algorithm, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + items: [ + 'HS256', + 'HS384', + 'HS512', + ].map((algorithm) { + return DropdownMenuItem( + value: algorithm, + child: Text(algorithm), + ); + }).toList(), + onChanged: (String? newAlgorithm) { + if (newAlgorithm != null) { + _updateJwtAuth(); + } + }, + ), + const SizedBox(height: 16), + Text( + "Secret", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 4), + TextField( + controller: _secretController, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + hintText: "Secret key", + hintStyle: Theme.of(context).textTheme.bodyMedium, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + onChanged: (value) => _updateJwtAuth(), + ), + const SizedBox(height: 16), + CheckboxListTile( + title: Text( + "Secret is Base64 encoded", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + value: _isSecretBase64Encoded, + contentPadding: EdgeInsets.zero, + controlAffinity: ListTileControlAffinity.leading, + onChanged: (bool? value) { + _updateJwtAuth(); + }, + ), + const SizedBox(height: 16), + Text( + "Payload (JSON format)", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 4), + TextField( + controller: _payloadController, + maxLines: 4, + decoration: InputDecoration( + constraints: BoxConstraints( + maxWidth: MediaQuery.sizeOf(context).width - 100, + ), + contentPadding: const EdgeInsets.all(18), + hintText: + '{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}', + hintStyle: Theme.of(context).textTheme.bodyMedium, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + onChanged: (value) => _updateJwtAuth(), + ), + // const SizedBox(height: 16), + // if (currentAddTokenTo == 'header') ...[ + // Text( + // "Header Prefix", + // style: TextStyle( + // fontWeight: FontWeight.bold, + // ), + // ), + // SizedBox(height: 4), + // TextField( + // controller: jwtHeaderPrefixController, + // decoration: InputDecoration( + // constraints: BoxConstraints( + // maxWidth: MediaQuery.sizeOf(context).width - 100, + // ), + // contentPadding: const EdgeInsets.all(18), + // hintText: "Bearer", + // hintStyle: Theme.of(context).textTheme.bodyMedium, + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // onChanged: (value) => updateAuth(ApiAuthModel( + // type: APIAuthType.jwt, + // jwt: AuthJwtModel( + // secret: jwtSecretController.text.trim(), + // payload: jwtPayloadController.text.trim(), + // addTokenTo: currentAddTokenTo, + // algorithm: currentAlgorithm, + // isSecretBase64Encoded: isSecretBase64Encoded, + // headerPrefix: jwtHeaderPrefixController.text.trim(), + // queryParamKey: jwtQueryParamKeyController.text.trim(), + // header: jwtHeaderController.text.trim(), + // ), + // )), + // ), + // const SizedBox(height: 16), + // ], + // if (currentAddTokenTo == 'query') ...[ + // Text( + // "Query Parameter Key", + // style: TextStyle( + // fontWeight: FontWeight.bold, + // ), + // ), + // SizedBox(height: 4), + // TextField( + // controller: jwtQueryParamKeyController, + // decoration: InputDecoration( + // constraints: BoxConstraints( + // maxWidth: MediaQuery.sizeOf(context).width - 100, + // ), + // contentPadding: const EdgeInsets.all(18), + // hintText: "token", + // hintStyle: Theme.of(context).textTheme.bodyMedium, + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // onChanged: (value) => updateAuth(ApiAuthModel( + // type: APIAuthType.jwt, + // jwt: AuthJwtModel( + // secret: jwtSecretController.text.trim(), + // payload: jwtPayloadController.text.trim(), + // addTokenTo: currentAddTokenTo, + // algorithm: currentAlgorithm, + // isSecretBase64Encoded: isSecretBase64Encoded, + // headerPrefix: jwtHeaderPrefixController.text.trim(), + // queryParamKey: jwtQueryParamKeyController.text.trim(), + // header: jwtHeaderController.text.trim(), + // ), + // )), + // ), + // const SizedBox(height: 16), + // ], + // Text( + // "JWT Headers (JSON format)", + // style: TextStyle( + // fontWeight: FontWeight.bold, + // ), + // ), + // SizedBox(height: 4), + // TextField( + // controller: jwtHeaderController, + // maxLines: 3, + // decoration: InputDecoration( + // constraints: BoxConstraints( + // maxWidth: MediaQuery.sizeOf(context).width - 100, + // ), + // contentPadding: const EdgeInsets.all(18), + // hintText: '{"typ": "JWT", "alg": "HS256"}', + // hintStyle: Theme.of(context).textTheme.bodyMedium, + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // onChanged: (value) => updateAuth( + // ApiAuthModel( + // type: APIAuthType.jwt, + // jwt: AuthJwtModel( + // secret: jwtSecretController.text.trim(), + // payload: jwtPayloadController.text.trim(), + // addTokenTo: currentAddTokenTo, + // algorithm: currentAlgorithm, + // isSecretBase64Encoded: isSecretBase64Encoded, + // headerPrefix: jwtHeaderPrefixController.text.trim(), + // queryParamKey: jwtQueryParamKeyController.text.trim(), + // header: jwtHeaderController.text.trim(), + // ), + // ), + // ), + // ), + ], + ); + } + + void _updateJwtAuth() { + widget.updateAuth( + widget.authData?.copyWith( + type: APIAuthType.jwt, + jwt: AuthJwtModel( + secret: _secretController.text.trim(), + payload: _payloadController.text.trim(), + addTokenTo: _addTokenTo, + algorithm: _algorithm, + isSecretBase64Encoded: _isSecretBase64Encoded, + headerPrefix: 'Bearer', + queryParamKey: 'token', + header: '', + ), + ), + ); + } +} diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_auth.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_auth.dart index 644c7b74..6d401ea7 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_auth.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_auth.dart @@ -1,3 +1,7 @@ +import 'package:apidash/screens/common_widgets/auth/api_key_auth_fields.dart'; +import 'package:apidash/screens/common_widgets/auth/basic_auth_fields.dart'; +import 'package:apidash/screens/common_widgets/auth/bearer_auth_fields.dart'; +import 'package:apidash/screens/common_widgets/auth/jwt_auth_fields.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash_core/apidash_core.dart'; @@ -81,597 +85,27 @@ class EditAuthType extends ConsumerWidget { switch (authData?.type) { case APIAuthType.basic: - final usernameController = TextEditingController( - text: authData?.basic?.username ?? '', + return BasicAuthFields( + authData: authData, + updateAuth: updateAuth, ); - final passwordController = TextEditingController( - text: authData?.basic?.password ?? '', - ); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Username", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 4, - ), - TextField( - controller: usernameController, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - hintText: "Username", - hintStyle: Theme.of(context).textTheme.bodyMedium, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onChanged: (value) => updateAuth(authData?.copyWith( - type: APIAuthType.basic, - basic: AuthBasicAuthModel( - username: usernameController.text.trim(), - password: passwordController.text.trim(), - ), - )), - ), - SizedBox( - height: 16, - ), - Text( - "Password", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 4, - ), - TextField( - controller: passwordController, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - hintText: "Password", - hintStyle: Theme.of(context).textTheme.bodyMedium, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - obscureText: true, - onChanged: (value) => updateAuth( - authData?.copyWith( - type: APIAuthType.basic, - basic: AuthBasicAuthModel( - username: usernameController.text.trim(), - password: passwordController.text.trim(), - ), - ), - ), - ), - ], - ); - case APIAuthType.bearer: - final tokenController = TextEditingController( - text: authData?.bearer?.token ?? '', + return BearerAuthFields( + authData: authData, + updateAuth: updateAuth, ); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Token", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 4, - ), - TextField( - controller: tokenController, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - hintText: "Token", - hintStyle: Theme.of(context).textTheme.bodyMedium, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onChanged: (value) => updateAuth( - authData?.copyWith( - type: APIAuthType.bearer, - bearer: AuthBearerModel(token: tokenController.text.trim()), - ), - ), - ), - ], - ); - case APIAuthType.apiKey: - final keyController = TextEditingController( - text: authData?.apikey?.key ?? '', + return ApiKeyAuthFields( + authData: authData, + updateAuth: updateAuth, ); - final nameController = TextEditingController( - text: authData?.apikey?.name ?? 'x-api-key', - ); - final currentLocation = authData?.apikey?.location ?? 'header'; - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Add to", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 4, - ), - DropdownButtonFormField( - value: currentLocation, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - items: [ - DropdownMenuItem( - value: 'header', - child: Text('Header'), - ), - DropdownMenuItem( - value: 'query', - child: Text('Query Params'), - ), - ], - onChanged: (String? newLocation) { - if (newLocation != null) { - updateAuth( - authData?.copyWith( - type: APIAuthType.apiKey, - apikey: AuthApiKeyModel( - key: keyController.text, - name: nameController.text, - location: newLocation, - ), - ), - ); - } - }, - ), - const SizedBox(height: 16), - Text( - "Header/Query Param Name", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 4, - ), - TextField( - controller: nameController, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - hintText: "Header/Query Param Name", - hintStyle: Theme.of(context).textTheme.bodyMedium, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onChanged: (value) => updateAuth( - authData?.copyWith( - type: APIAuthType.apiKey, - apikey: AuthApiKeyModel( - key: keyController.text, - name: nameController.text.trim(), - location: currentLocation, - ), - ), - ), - ), - const SizedBox(height: 16), - Text( - "API Key", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox( - height: 4, - ), - TextField( - controller: keyController, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - hintText: "API Key", - hintStyle: Theme.of(context).textTheme.bodyMedium, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onChanged: (value) => updateAuth( - authData?.copyWith( - type: APIAuthType.apiKey, - apikey: AuthApiKeyModel( - key: keyController.text.trim(), - name: nameController.text, - location: currentLocation, - ), - ), - ), - ), - ], - ); - case APIAuthType.jwt: - final jwtSecretController = TextEditingController( - text: authData?.jwt?.secret ?? '', + return JwtAuthFields( + authData: authData, + updateAuth: updateAuth, ); - final jwtPayloadController = TextEditingController( - text: authData?.jwt?.payload ?? '', - ); - final jwtHeaderPrefixController = TextEditingController( - text: authData?.jwt?.headerPrefix ?? 'Bearer', - ); - final jwtQueryParamKeyController = TextEditingController( - text: authData?.jwt?.queryParamKey ?? 'token', - ); - final jwtHeaderController = TextEditingController( - text: authData?.jwt?.header ?? '', - ); - - final currentAddTokenTo = authData?.jwt?.addTokenTo ?? 'header'; - final currentAlgorithm = authData?.jwt?.algorithm ?? 'HS256'; - final isSecretBase64Encoded = - authData?.jwt?.isSecretBase64Encoded ?? false; - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Add JWT token to", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 4), - DropdownButtonFormField( - value: currentAddTokenTo, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - items: [ - DropdownMenuItem( - value: 'header', - child: Text('Request Header'), - ), - DropdownMenuItem( - value: 'query', - child: Text('Query Parameters'), - ), - ], - onChanged: (String? newAddTokenTo) { - if (newAddTokenTo != null) { - updateAuth( - authData?.copyWith( - type: APIAuthType.jwt, - jwt: AuthJwtModel( - secret: jwtSecretController.text.trim(), - payload: jwtPayloadController.text.trim(), - addTokenTo: newAddTokenTo, - algorithm: currentAlgorithm, - isSecretBase64Encoded: isSecretBase64Encoded, - headerPrefix: jwtHeaderPrefixController.text.trim(), - queryParamKey: jwtQueryParamKeyController.text.trim(), - header: jwtHeaderController.text.trim(), - ), - ), - ); - } - }, - ), - const SizedBox(height: 16), - Text( - "Algorithm", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 4), - DropdownButtonFormField( - value: currentAlgorithm, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - items: [ - 'HS256', - 'HS384', - 'HS512', - ].map((algorithm) { - return DropdownMenuItem( - value: algorithm, - child: Text(algorithm), - ); - }).toList(), - onChanged: (String? newAlgorithm) { - if (newAlgorithm != null) { - updateAuth( - authData?.copyWith( - type: APIAuthType.jwt, - jwt: AuthJwtModel( - secret: jwtSecretController.text.trim(), - payload: jwtPayloadController.text.trim(), - addTokenTo: currentAddTokenTo, - algorithm: newAlgorithm, - isSecretBase64Encoded: isSecretBase64Encoded, - headerPrefix: jwtHeaderPrefixController.text.trim(), - queryParamKey: jwtQueryParamKeyController.text.trim(), - header: jwtHeaderController.text.trim(), - ), - ), - ); - } - }, - ), - const SizedBox(height: 16), - Text( - "Secret", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 4), - TextField( - controller: jwtSecretController, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - hintText: "Secret key", - hintStyle: Theme.of(context).textTheme.bodyMedium, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onChanged: (value) => updateAuth( - authData?.copyWith( - type: APIAuthType.jwt, - jwt: AuthJwtModel( - secret: jwtSecretController.text.trim(), - payload: jwtPayloadController.text.trim(), - addTokenTo: currentAddTokenTo, - algorithm: currentAlgorithm, - isSecretBase64Encoded: isSecretBase64Encoded, - headerPrefix: jwtHeaderPrefixController.text.trim(), - queryParamKey: jwtQueryParamKeyController.text.trim(), - header: jwtHeaderController.text.trim(), - ), - ), - ), - ), - const SizedBox(height: 16), - CheckboxListTile( - title: Text( - "Secret is Base64 encoded", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - value: isSecretBase64Encoded, - contentPadding: EdgeInsets.zero, - controlAffinity: ListTileControlAffinity.leading, - onChanged: (bool? value) { - updateAuth( - authData?.copyWith( - type: APIAuthType.jwt, - jwt: AuthJwtModel( - secret: jwtSecretController.text.trim(), - payload: jwtPayloadController.text.trim(), - addTokenTo: currentAddTokenTo, - algorithm: currentAlgorithm, - isSecretBase64Encoded: value ?? false, - headerPrefix: jwtHeaderPrefixController.text.trim(), - queryParamKey: jwtQueryParamKeyController.text.trim(), - header: jwtHeaderController.text.trim(), - ), - ), - ); - }, - ), - const SizedBox(height: 16), - Text( - "Payload (JSON format)", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 4), - TextField( - controller: jwtPayloadController, - maxLines: 4, - decoration: InputDecoration( - constraints: BoxConstraints( - maxWidth: MediaQuery.sizeOf(context).width - 100, - ), - contentPadding: const EdgeInsets.all(18), - hintText: - '{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}', - hintStyle: Theme.of(context).textTheme.bodyMedium, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onChanged: (value) => updateAuth( - authData?.copyWith( - type: APIAuthType.jwt, - jwt: AuthJwtModel( - secret: jwtSecretController.text.trim(), - payload: jwtPayloadController.text.trim(), - addTokenTo: currentAddTokenTo, - algorithm: currentAlgorithm, - isSecretBase64Encoded: isSecretBase64Encoded, - headerPrefix: jwtHeaderPrefixController.text.trim(), - queryParamKey: jwtQueryParamKeyController.text.trim(), - header: jwtHeaderController.text.trim(), - ), - ), - ), - ), - // const SizedBox(height: 16), - // if (currentAddTokenTo == 'header') ...[ - // Text( - // "Header Prefix", - // style: TextStyle( - // fontWeight: FontWeight.bold, - // ), - // ), - // SizedBox(height: 4), - // TextField( - // controller: jwtHeaderPrefixController, - // decoration: InputDecoration( - // constraints: BoxConstraints( - // maxWidth: MediaQuery.sizeOf(context).width - 100, - // ), - // contentPadding: const EdgeInsets.all(18), - // hintText: "Bearer", - // hintStyle: Theme.of(context).textTheme.bodyMedium, - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(8), - // ), - // ), - // onChanged: (value) => updateAuth(ApiAuthModel( - // type: APIAuthType.jwt, - // jwt: AuthJwtModel( - // secret: jwtSecretController.text.trim(), - // payload: jwtPayloadController.text.trim(), - // addTokenTo: currentAddTokenTo, - // algorithm: currentAlgorithm, - // isSecretBase64Encoded: isSecretBase64Encoded, - // headerPrefix: jwtHeaderPrefixController.text.trim(), - // queryParamKey: jwtQueryParamKeyController.text.trim(), - // header: jwtHeaderController.text.trim(), - // ), - // )), - // ), - // const SizedBox(height: 16), - // ], - // if (currentAddTokenTo == 'query') ...[ - // Text( - // "Query Parameter Key", - // style: TextStyle( - // fontWeight: FontWeight.bold, - // ), - // ), - // SizedBox(height: 4), - // TextField( - // controller: jwtQueryParamKeyController, - // decoration: InputDecoration( - // constraints: BoxConstraints( - // maxWidth: MediaQuery.sizeOf(context).width - 100, - // ), - // contentPadding: const EdgeInsets.all(18), - // hintText: "token", - // hintStyle: Theme.of(context).textTheme.bodyMedium, - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(8), - // ), - // ), - // onChanged: (value) => updateAuth(ApiAuthModel( - // type: APIAuthType.jwt, - // jwt: AuthJwtModel( - // secret: jwtSecretController.text.trim(), - // payload: jwtPayloadController.text.trim(), - // addTokenTo: currentAddTokenTo, - // algorithm: currentAlgorithm, - // isSecretBase64Encoded: isSecretBase64Encoded, - // headerPrefix: jwtHeaderPrefixController.text.trim(), - // queryParamKey: jwtQueryParamKeyController.text.trim(), - // header: jwtHeaderController.text.trim(), - // ), - // )), - // ), - // const SizedBox(height: 16), - // ], - // Text( - // "JWT Headers (JSON format)", - // style: TextStyle( - // fontWeight: FontWeight.bold, - // ), - // ), - // SizedBox(height: 4), - // TextField( - // controller: jwtHeaderController, - // maxLines: 3, - // decoration: InputDecoration( - // constraints: BoxConstraints( - // maxWidth: MediaQuery.sizeOf(context).width - 100, - // ), - // contentPadding: const EdgeInsets.all(18), - // hintText: '{"typ": "JWT", "alg": "HS256"}', - // hintStyle: Theme.of(context).textTheme.bodyMedium, - // border: OutlineInputBorder( - // borderRadius: BorderRadius.circular(8), - // ), - // ), - // onChanged: (value) => updateAuth( - // ApiAuthModel( - // type: APIAuthType.jwt, - // jwt: AuthJwtModel( - // secret: jwtSecretController.text.trim(), - // payload: jwtPayloadController.text.trim(), - // addTokenTo: currentAddTokenTo, - // algorithm: currentAlgorithm, - // isSecretBase64Encoded: isSecretBase64Encoded, - // headerPrefix: jwtHeaderPrefixController.text.trim(), - // queryParamKey: jwtQueryParamKeyController.text.trim(), - // header: jwtHeaderController.text.trim(), - // ), - // ), - // ), - // ), - ], - ); - case APIAuthType.none: return const Text("No authentication selected."); - - // TODO: Implement digest, oauth1, oauth2 later default: return const Text("This auth type is not implemented yet."); } diff --git a/pubspec.lock b/pubspec.lock index 66394a8d..97ee4871 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -674,10 +674,10 @@ packages: dependency: "direct main" description: name: fvp - sha256: f5012756985f7c8c19caaea2d65baf8a6cf5fee9fe520e1fabb8bc61e1d5f468 + sha256: a2b6f305a5e559abc21b1be06ca0ffb5bb6b5b523d6d45eb8e78d53f3b89e9a2 url: "https://pub.dev" source: hosted - version: "0.30.0" + version: "0.32.1" glob: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f34e23ba..cf1e4cc5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,8 +32,7 @@ dependencies: flutter_portal: ^1.1.4 flutter_riverpod: ^2.5.1 flutter_svg: ^2.0.17 - fvp: ^0.30.0 - highlight: ^0.7.0 + fvp: ^0.32.1 highlighter: ^0.1.1 hive_flutter: ^1.1.0 hooks_riverpod: ^2.5.2