From 98d7375071c96419911973e4050be1a353c9673b Mon Sep 17 00:00:00 2001 From: Udhay-Adithya Date: Wed, 30 Jul 2025 11:08:29 +0530 Subject: [PATCH] feat: add hints and info texts --- lib/screens/common_widgets/auth/consts.dart | 76 +++++++++++++++++ .../common_widgets/auth/oauth1_fields.dart | 51 ++++++----- .../common_widgets/auth/oauth2_field.dart | 84 +++++++++++-------- 3 files changed, 159 insertions(+), 52 deletions(-) diff --git a/lib/screens/common_widgets/auth/consts.dart b/lib/screens/common_widgets/auth/consts.dart index 479f0980..63f0959e 100644 --- a/lib/screens/common_widgets/auth/consts.dart +++ b/lib/screens/common_widgets/auth/consts.dart @@ -63,6 +63,82 @@ const kHintJson = const kHeaderPrefix = 'Bearer'; const kQueryParamKey = 'token'; +// OAuth1 Auth +const kHintOAuth1ConsumerKey = "Consumer Key"; +const kInfoOAuth1ConsumerKey = + "The consumer key provided by the service provider to identify your application."; +const kHintOAuth1ConsumerSecret = "Consumer Secret"; +const kInfoOAuth1ConsumerSecret = + "The consumer secret provided by the service provider. Keep this secure and never expose it publicly."; +const kHintOAuth1AccessToken = "Access Token"; +const kInfoOAuth1AccessToken = + "The access token obtained after user authorization. This represents the user's permission to access their data."; +const kHintOAuth1TokenSecret = "Token Secret"; +const kInfoOAuth1TokenSecret = + "The token secret associated with the access token. Used to sign requests along with the consumer secret."; +const kHintOAuth1CallbackUrl = "Callback URL"; +const kInfoOAuth1CallbackUrl = + "The URL where the user will be redirected after authorization. Must match the URL registered with the service provider."; +const kHintOAuth1Verifier = "Verifier"; +const kInfoOAuth1Verifier = + "The verification code received after user authorization. Used to exchange the request token for an access token."; +const kHintOAuth1Timestamp = "Timestamp"; +const kInfoOAuth1Timestamp = + "Unix timestamp when the request is made. Usually generated automatically to prevent replay attacks."; +const kHintOAuth1Nonce = "Nonce"; +const kInfoOAuth1Nonce = + "A unique random string for each request. Helps prevent replay attacks and ensures request uniqueness."; +const kHintOAuth1Realm = "Realm"; +const kInfoOAuth1Realm = + "Optional realm parameter that defines the protection space. Some services require this for proper authentication."; +const kLabelOAuth1SignatureMethod = "Signature Method"; +const kTooltipOAuth1SignatureMethod = + "Select the signature method for OAuth 1.0 authentication"; + +// OAuth2 Auth +const kLabelOAuth2GrantType = "Grant Type"; +const kTooltipOAuth2GrantType = "Select OAuth 2.0 grant type"; +const kHintOAuth2AuthorizationUrl = "Authorization URL"; +const kInfoOAuth2AuthorizationUrl = + "The authorization endpoint URL where users are redirected to grant permission to your application."; +const kHintOAuth2AccessTokenUrl = "Access Token URL"; +const kInfoOAuth2AccessTokenUrl = + "The token endpoint URL where authorization codes are exchanged for access tokens."; +const kHintOAuth2ClientId = "Client ID"; +const kInfoOAuth2ClientId = + "The client identifier issued to your application by the authorization server."; +const kHintOAuth2ClientSecret = "Client Secret"; +const kInfoOAuth2ClientSecret = + "The client secret issued to your application. Keep this secure and never expose it publicly."; +const kHintOAuth2RedirectUrl = "Redirect URL"; +const kInfoOAuth2RedirectUrl = + "The URL where users are redirected after authorization. Must match the URL registered with the service."; +const kHintOAuth2Scope = "Scope"; +const kInfoOAuth2Scope = + "Space-separated list of permissions your application is requesting access to."; +const kHintOAuth2State = "State"; +const kInfoOAuth2State = + "An unguessable random string used to protect against cross-site request forgery attacks."; +const kHintOAuth2Username = "Username"; +const kInfoOAuth2Username = + "Your username for resource owner password credentials grant type."; +const kHintOAuth2Password = "Password"; +const kInfoOAuth2Password = + "Your password for resource owner password credentials grant type."; +const kHintOAuth2RefreshToken = "Refresh Token"; +const kInfoOAuth2RefreshToken = + "Token used to obtain new access tokens when the current access token expires."; +const kHintOAuth2IdentityToken = "Identity Token"; +const kInfoOAuth2IdentityToken = + "JWT token containing user identity information, typically used in OpenID Connect flows."; +const kHintOAuth2AccessToken = "Access Token"; +const kInfoOAuth2AccessToken = + "The token used to access protected resources on behalf of the user."; +const kLabelOAuth2CodeChallengeMethod = "Code Challenge Method"; +const kTooltipOAuth2CodeChallengeMethod = + "Code challenge method for PKCE (Proof Key for Code Exchange)"; +const kButtonClearOAuth2Session = "Clear OAuth2 Session"; + //AuthPAge const kLabelSelectAuthType = "Authentication Type"; const kTooltipSelectAuth = "Select Authentication Type"; diff --git a/lib/screens/common_widgets/auth/oauth1_fields.dart b/lib/screens/common_widgets/auth/oauth1_fields.dart index 47381d2d..f942c167 100644 --- a/lib/screens/common_widgets/auth/oauth1_fields.dart +++ b/lib/screens/common_widgets/auth/oauth1_fields.dart @@ -3,6 +3,7 @@ import 'package:apidash/widgets/widgets.dart'; import 'package:apidash_core/apidash_core.dart'; import 'package:apidash_design_system/widgets/widgets.dart'; import 'package:flutter/material.dart'; +import 'consts.dart'; class OAuth1Fields extends StatefulWidget { final AuthModel? authData; @@ -95,20 +96,22 @@ class _OAuth1FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _consumerKeyController, - hintText: "Consumer Key", + hintText: kHintOAuth1ConsumerKey, + infoText: kInfoOAuth1ConsumerKey, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _consumerSecretController, - hintText: "Consumer Secret", + hintText: kHintOAuth1ConsumerSecret, + infoText: kInfoOAuth1ConsumerSecret, isObscureText: true, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), Text( - "Signature Method", + kLabelOAuth1SignatureMethod, style: TextStyle( fontWeight: FontWeight.normal, fontSize: 14, @@ -118,65 +121,75 @@ class _OAuth1FieldsState extends State { ADPopupMenu( value: _signatureMethodController.displayType, values: OAuth1SignatureMethod.values.map((e) => (e, e.displayType)), - tooltip: "this algorithm will be used to produce the digest", + tooltip: kTooltipOAuth1SignatureMethod, isOutlined: true, - onChanged: (OAuth1SignatureMethod? newAlgo) { - if (newAlgo != null) { - setState(() { - _signatureMethodController = newAlgo; - }); + onChanged: widget.readOnly + ? null + : (OAuth1SignatureMethod? newAlgo) { + if (newAlgo != null) { + setState(() { + _signatureMethodController = newAlgo; + }); - _updateOAuth1(); - } - }, + _updateOAuth1(); + } + }, ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _accessTokenController, - hintText: "Access Token", + hintText: kHintOAuth1AccessToken, + infoText: kInfoOAuth1AccessToken, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _tokenSecretController, - hintText: "Token Secret", + hintText: kHintOAuth1TokenSecret, + infoText: kInfoOAuth1TokenSecret, + isObscureText: true, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _callbackUrlController, - hintText: "Callback URL", + hintText: kHintOAuth1CallbackUrl, + infoText: kInfoOAuth1CallbackUrl, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _verifierController, - hintText: "Verifier", + hintText: kHintOAuth1Verifier, + infoText: kInfoOAuth1Verifier, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _timestampController, - hintText: "Timestamp", + hintText: kHintOAuth1Timestamp, + infoText: kInfoOAuth1Timestamp, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _nonceController, - hintText: "Nonce", + hintText: kHintOAuth1Nonce, + infoText: kInfoOAuth1Nonce, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), AuthTextField( readOnly: widget.readOnly, controller: _realmController, - hintText: "Realm", + hintText: kHintOAuth1Realm, + infoText: kInfoOAuth1Realm, onChanged: (_) => _updateOAuth1(), ), const SizedBox(height: 16), diff --git a/lib/screens/common_widgets/auth/oauth2_field.dart b/lib/screens/common_widgets/auth/oauth2_field.dart index 4d13ccf4..f346154a 100644 --- a/lib/screens/common_widgets/auth/oauth2_field.dart +++ b/lib/screens/common_widgets/auth/oauth2_field.dart @@ -5,6 +5,7 @@ import 'package:apidash/widgets/field_auth.dart'; import 'package:apidash_core/apidash_core.dart'; import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:flutter/material.dart'; +import 'consts.dart'; class OAuth2Fields extends StatefulWidget { final AuthModel? authData; @@ -102,24 +103,26 @@ class _OAuth2FieldsState extends State { physics: ClampingScrollPhysics(), children: [ Text( - "Grant Type", + kLabelOAuth2GrantType, style: Theme.of(context).textTheme.labelLarge, ), kVSpacer5, ADPopupMenu( value: _grantType.displayType, values: OAuth2GrantType.values.map((e) => (e, e.displayType)), - tooltip: "Select OAuth 2.0 grant type", + tooltip: kTooltipOAuth2GrantType, isOutlined: true, - onChanged: (OAuth2GrantType? newGrantType) { - if (newGrantType != null && newGrantType != _grantType) { - setState(() { - _grantType = newGrantType; - }); + onChanged: widget.readOnly + ? null + : (OAuth2GrantType? newGrantType) { + if (newGrantType != null && newGrantType != _grantType) { + setState(() { + _grantType = newGrantType; + }); - _updateOAuth2(); - } - }, + _updateOAuth2(); + } + }, ), kVSpacer16, if (_shouldShowField(OAuth2Field.authorizationUrl)) @@ -127,7 +130,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _authorizationUrlController, - hintText: "Authorization URL", + hintText: kHintOAuth2AuthorizationUrl, + infoText: kInfoOAuth2AuthorizationUrl, onChanged: (_) => _updateOAuth2(), ), ), @@ -136,7 +140,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _usernameController, - hintText: "Username", + hintText: kHintOAuth2Username, + infoText: kInfoOAuth2Username, onChanged: (_) => _updateOAuth2(), ), ), @@ -145,7 +150,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _passwordController, - hintText: "Password", + hintText: kHintOAuth2Password, + infoText: kInfoOAuth2Password, isObscureText: true, onChanged: (_) => _updateOAuth2(), ), @@ -155,7 +161,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _accessTokenUrlController, - hintText: "Access Token URL", + hintText: kHintOAuth2AccessTokenUrl, + infoText: kInfoOAuth2AccessTokenUrl, onChanged: (_) => _updateOAuth2(), ), ), @@ -164,7 +171,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _clientIdController, - hintText: "Client ID", + hintText: kHintOAuth2ClientId, + infoText: kInfoOAuth2ClientId, onChanged: (_) => _updateOAuth2(), ), ), @@ -173,14 +181,15 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _clientSecretController, - hintText: "Client Secret", + hintText: kHintOAuth2ClientSecret, + infoText: kInfoOAuth2ClientSecret, isObscureText: true, onChanged: (_) => _updateOAuth2(), ), ), if (_shouldShowField(OAuth2Field.codeChallengeMethod)) ...[ Text( - "Code Challenge Method", + kLabelOAuth2CodeChallengeMethod, style: Theme.of(context).textTheme.labelLarge, ), kVSpacer5, @@ -190,17 +199,20 @@ class _OAuth2FieldsState extends State { ('SHA-256', 'sha-256'), ('Plaintext', 'plaintext'), ], - tooltip: "Code challenge method for PKCE", + tooltip: kTooltipOAuth2CodeChallengeMethod, isOutlined: true, - onChanged: (String? newMethod) { - if (newMethod != null && newMethod != _codeChallengeMethod) { - setState(() { - _codeChallengeMethod = newMethod; - }); + onChanged: widget.readOnly + ? null + : (String? newMethod) { + if (newMethod != null && + newMethod != _codeChallengeMethod) { + setState(() { + _codeChallengeMethod = newMethod; + }); - _updateOAuth2(); - } - }, + _updateOAuth2(); + } + }, ), kVSpacer16, ], @@ -209,7 +221,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _redirectUrlController, - hintText: "Redirect URL", + hintText: kHintOAuth2RedirectUrl, + infoText: kInfoOAuth2RedirectUrl, onChanged: (_) => _updateOAuth2(), ), ), @@ -218,7 +231,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _scopeController, - hintText: "Scope", + hintText: kHintOAuth2Scope, + infoText: kInfoOAuth2Scope, onChanged: (_) => _updateOAuth2(), ), ), @@ -227,13 +241,14 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _stateController, - hintText: "State", + hintText: kHintOAuth2State, + infoText: kInfoOAuth2State, onChanged: (_) => _updateOAuth2(), ), ), ..._buildFieldWithSpacing( ADTextButton( - label: "Clear OAuth2 Session", + label: kButtonClearOAuth2Session, onPressed: clearStoredCredentials, ), ), @@ -243,7 +258,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _refreshTokenController, - hintText: "Refresh Token", + hintText: kHintOAuth2RefreshToken, + infoText: kInfoOAuth2RefreshToken, onChanged: (_) => _updateOAuth2(), ), ), @@ -251,7 +267,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _identityTokenController, - hintText: "Identity Token", + hintText: kHintOAuth2IdentityToken, + infoText: kInfoOAuth2IdentityToken, onChanged: (_) => _updateOAuth2(), ), ), @@ -259,7 +276,8 @@ class _OAuth2FieldsState extends State { AuthTextField( readOnly: widget.readOnly, controller: _accessTokenController, - hintText: "Access Token", + hintText: kHintOAuth2AccessToken, + infoText: kInfoOAuth2AccessToken, onChanged: (_) => _updateOAuth2(), ), ),