From 0673ad1289989ef0b774b8b49677fb7ab13e5050 Mon Sep 17 00:00:00 2001 From: Cristian Hernandez Date: Mon, 16 Sep 2024 12:05:51 -0700 Subject: [PATCH 1/5] Fixes for issues found in QA: - Update angeleno site urls to new sandbox urls - Allow text to be highlighted in MFA TOTP modal - Update copyright date - Fixed unable to disable immediately after enabling #123 - Fixed scrollbar over text inputs and edit button on Profile page - Fixed error showing prior to user interaction. Disabled continue option until fields have values. --- functions/auth0/api/auth0.js | 71 ++-- lib/views/dialogs/authenticator.dart | 29 +- lib/views/dialogs/mobile.dart | 86 +++-- .../screens/advanced_security_screen.dart | 108 +++--- lib/views/screens/home_screen.dart | 11 +- lib/views/screens/profile_screen.dart | 356 +++++++++--------- 6 files changed, 340 insertions(+), 321 deletions(-) diff --git a/functions/auth0/api/auth0.js b/functions/auth0/api/auth0.js index d379d36..d5b3c4d 100644 --- a/functions/auth0/api/auth0.js +++ b/functions/auth0/api/auth0.js @@ -29,6 +29,7 @@ export const updateUser = onRequest(async (req, res) => { if (user.lastName) { updatedUserObject['family_name'] = user.lastName; + updatedUserObject['name'] += ` ${user.lastName}`; } const primaryAddress = {}; @@ -354,6 +355,40 @@ export const unenrollMFA = onRequest(async (req, res) => { } }); +export const removeConnection = onRequest(async (req, res) => { + try { + const { + connectionId + } = req.body; + + if (!connectionId) { + res.status(400).send('Invalid request - missing required fields.'); + return; + } + + const config = { + method: 'delete', + maxBodyLength: Infinity, + url: `https://${auth0Domain}/api/v2/grants/${connectionId}`, + headers: { + 'Authorization': `Bearer ${await getAccessToken()}` + } + }; + + await axios.request(config) + res.status(200).send(); + } catch (error) { + console.log(error); + + const { + status = 500, + message = '', + } = error.response; + + return res.status(status).send(message); + }; +}); + const getConnectedServices = async (userId) => { if (!userId) { @@ -427,38 +462,4 @@ const getConnectedServices = async (userId) => { return res.status(status).send(message); } -}; - -export const removeConnection = onRequest(async (req, res) => { - try { - const { - connectionId - } = req.body; - - if (!connectionId) { - res.status(400).send('Invalid request - missing required fields.'); - return; - } - - const config = { - method: 'delete', - maxBodyLength: Infinity, - url: `https://${auth0Domain}/api/v2/grants/${connectionId}`, - headers: { - 'Authorization': `Bearer ${await getAccessToken()}` - } - }; - - await axios.request(config) - res.status(200).send(); - } catch (error) { - console.log(error); - - const { - status = 500, - message = '', - } = error.response; - - return res.status(status).send(message); - }; -}); +}; \ No newline at end of file diff --git a/lib/views/dialogs/authenticator.dart b/lib/views/dialogs/authenticator.dart index 09da329..cca3ad8 100644 --- a/lib/views/dialogs/authenticator.dart +++ b/lib/views/dialogs/authenticator.dart @@ -36,7 +36,6 @@ class _AuthenticatorDialogState extends State { String qrCodeAltString = ''; String mfaToken = ''; - String userPassword = ''; bool obscurePassword = true; @override @@ -45,6 +44,10 @@ class _AuthenticatorDialogState extends State { userProvider = widget.userProvider; auth0UserApi = widget.auth0UserApi; + + passwordField.addListener(() { + setState(() {}); + }); } @override @@ -151,7 +154,7 @@ class _AuthenticatorDialogState extends State { children: [ dialogClose, TextButton( - onPressed: () { + onPressed: passwordField.text.isEmpty ? null : () { enrollTOTP(); }, child: const Text('Continue'), @@ -183,7 +186,7 @@ class _AuthenticatorDialogState extends State { obscureText: obscurePassword, enableSuggestions: false, autocorrect: false, - autovalidateMode: AutovalidateMode.always, + autovalidateMode: AutovalidateMode.onUserInteraction, validator: (final value) { if (value == null || value.trim().isEmpty) { return 'Password is required'; @@ -251,14 +254,14 @@ class _AuthenticatorDialogState extends State { const SizedBox(height: 20), const Text('If unable to scan, please enter the code below:'), const SizedBox(height: 15), - Text( - qrCodeAltString, - style: const TextStyle( - decoration: TextDecoration.none, - color: Colors.black, - fontSize: 14.0, - fontWeight: FontWeight.normal - ) + SelectableText( + qrCodeAltString, + style: const TextStyle( + decoration: TextDecoration.none, + color: Colors.black, + fontSize: 14.0, + fontWeight: FontWeight.normal + ) ) ], ), @@ -275,7 +278,7 @@ class _AuthenticatorDialogState extends State { children: [ dialogClose, TextButton( - onPressed: () { + onPressed: totpCode.isEmpty ? null : () { confirmTOTP(); }, child: const Text('Finish'), @@ -296,7 +299,7 @@ class _AuthenticatorDialogState extends State { child: TextFormField( key: const Key('totpCode'), autofocus: true, - autovalidateMode: AutovalidateMode.always, + autovalidateMode: AutovalidateMode.onUserInteraction, validator: (final value) { if (value == null || value.trim().isEmpty) { return 'Code is required'; diff --git a/lib/views/dialogs/mobile.dart b/lib/views/dialogs/mobile.dart index ccf6d0a..63c27e7 100644 --- a/lib/views/dialogs/mobile.dart +++ b/lib/views/dialogs/mobile.dart @@ -50,7 +50,7 @@ class _MobileDialogState extends State { bool validPhoneNumber = false; int _pageIndex = 0; - late List dialogNext; + // late List dialogNext; @override void initState() { @@ -60,31 +60,9 @@ class _MobileDialogState extends State { api = widget.userApi; channel = widget.channel; - dialogNext = [ - TextButton( - onPressed: () { - try { - if (!validPhoneNumber && isNotTestMode) { - return; - } - _navigateToNextPage(); - } catch (e) {} - }, - child: const Text('Continue'), - ), - TextButton( - onPressed: () { - enrollMobile(); - }, - child: const Text('Continue'), - ), - TextButton( - onPressed: () { - confirmCode(); - }, - child: const Text('Continue') - ) - ]; + passwordField.addListener(() { + setState(() {}); + }); } @override @@ -94,6 +72,32 @@ class _MobileDialogState extends State { super.dispose(); } + List get dialogNext => [ + TextButton( + onPressed: !validPhoneNumber && isNotTestMode ? null : () { + try { + if (!validPhoneNumber && isNotTestMode) { + return; + } + _navigateToNextPage(); + } catch (e) {} + }, + child: const Text('Continue'), + ), + TextButton( + onPressed: passwordField.text.isEmpty ? null : () { + enrollMobile(); + }, + child: const Text('Continue'), + ), + TextButton( + onPressed: codeProvided.isEmpty ? null : () { + confirmCode(); + }, + child: const Text('Continue') + ) + ]; + Widget get dialogClose => IconButton( alignment: Alignment.centerLeft, onPressed: () { @@ -216,7 +220,9 @@ class _MobileDialogState extends State { phoneNumber = number.phoneNumber!; }, onInputValidated: (final bool value) { - validPhoneNumber = value; + setState(() { + validPhoneNumber = value; + }); }, autoValidateMode: isNotTestMode ? AutovalidateMode.onUserInteraction @@ -256,7 +262,7 @@ class _MobileDialogState extends State { obscureText: obscurePassword, enableSuggestions: false, autocorrect: false, - autovalidateMode: AutovalidateMode.always, + autovalidateMode: AutovalidateMode.onUserInteraction, validator: (final value) { if (value == null || value.trim().isEmpty) { return 'Password is required'; @@ -264,17 +270,17 @@ class _MobileDialogState extends State { return null; }, decoration: InputDecoration( - suffixIcon: IconButton( - key: const Key('toggle_password'), - onPressed: () { - setState(() { - obscurePassword = !obscurePassword; - }); - }, - icon: Icon( - obscurePassword ? Icons.visibility : Icons.visibility_off - ), - ) + suffixIcon: IconButton( + key: const Key('toggle_password'), + onPressed: () { + setState(() { + obscurePassword = !obscurePassword; + }); + }, + icon: Icon( + obscurePassword ? Icons.visibility : Icons.visibility_off + ), + ) ), ), ), @@ -296,7 +302,7 @@ class _MobileDialogState extends State { child: TextFormField( key: const Key('phoneCode'), autofocus: true, - autovalidateMode: AutovalidateMode.always, + autovalidateMode: AutovalidateMode.onUserInteraction, validator: (final value) { if (value == null || value.trim().isEmpty) { return 'Code is required'; diff --git a/lib/views/screens/advanced_security_screen.dart b/lib/views/screens/advanced_security_screen.dart index 01069c6..c6a75ed 100644 --- a/lib/views/screens/advanced_security_screen.dart +++ b/lib/views/screens/advanced_security_screen.dart @@ -46,7 +46,13 @@ class _AdvancedSecurityState extends State { super.initState(); userProvider = widget.userProvider; auth0UserApi = widget.auth0UserApi; - _authMethods = getAuthenticationMethods(); + _triggerAuthMethods(); + } + + void _triggerAuthMethods() { + setState(() { + _authMethods = getAuthenticationMethods(); + }); } Future getAuthenticationMethods() async { @@ -158,12 +164,12 @@ class _AdvancedSecurityState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Semantics( - header: true, - child: const Text( - 'Multi-Factor Authentication', - textAlign: TextAlign.left, - style: headerStyle - ) + header: true, + child: const Text( + 'Multi-Factor Authentication', + textAlign: TextAlign.left, + style: headerStyle + ) ), const SizedBox(height: 10), Row( @@ -179,34 +185,34 @@ class _AdvancedSecurityState extends State { FilledButton.tonal( key: const Key('disableAuthenticator'), onPressed: () => showDialog( - context: context, - builder: (final BuildContext context) => AlertDialog( - title: const Text('Remove authenticator app?'), - content: const SingleChildScrollView( - child: ListBody( - children: [ - // ignore: avoid_escaping_inner_quotes - Text('You won\'t be able to use your ' - 'authenticator app to sign into your Angeleno ' - 'Account.') - ], - ) + context: context, + builder: (final BuildContext context) => AlertDialog( + title: const Text('Remove authenticator app?'), + content: const SingleChildScrollView( + child: ListBody( + children: [ + // ignore: avoid_escaping_inner_quotes + Text('You won\'t be able to use your ' + 'authenticator app to sign into your Angeleno ' + 'Account.') + ], + ) + ), + actions: [ + TextButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.pop(context); + }, ), - actions: [ - TextButton( - child: const Text('Cancel'), - onPressed: () { - Navigator.pop(context); - }, - ), - TextButton( - child: const Text('Ok'), - onPressed: () { - disableMFA(totpAuthId, 'totp'); - }, - ) - ], - ) + TextButton( + child: const Text('Ok'), + onPressed: () { + disableMFA(totpAuthId, 'totp'); + }, + ) + ], + ) ).then((final value) { if (value != null && value == HttpStatus.ok) { setState(() { @@ -218,24 +224,22 @@ class _AdvancedSecurityState extends State { ) : FilledButton( - key: const Key('enableAuthenticator'), - onPressed: () { - showDialog( - context: context, - builder: (final BuildContext context) => - AuthenticatorDialog( - userProvider: userProvider, - auth0UserApi: auth0UserApi - ), - ).then((final value) { - if (value != null && value == HttpStatus.ok){ - setState(() { - authenticatorEnabled = true; - }); - } - }); - }, - child: const Text('Enable') + key: const Key('enableAuthenticator'), + onPressed: () { + showDialog( + context: context, + builder: (final BuildContext context) => + AuthenticatorDialog( + userProvider: userProvider, + auth0UserApi: auth0UserApi + ), + ).then((final value) { + if (value != null && value == HttpStatus.ok){ + _triggerAuthMethods(); + } + }); + }, + child: const Text('Enable') ), ], ), diff --git a/lib/views/screens/home_screen.dart b/lib/views/screens/home_screen.dart index d35aed6..7c44b95 100644 --- a/lib/views/screens/home_screen.dart +++ b/lib/views/screens/home_screen.dart @@ -24,6 +24,7 @@ class _MyHomePageState extends State { late User user; late OverlayProvider overlayProvider; int _selectedIndex = 0; + final currentYear = DateTime.now().year; @override void initState() { @@ -72,17 +73,17 @@ class _MyHomePageState extends State { switch(index) { case 3: await launchUrl( - Uri.parse('https://angeleno.lacity.org/') + Uri.parse('https://sandbox.account.lacity.gov/') ); break; case 4: await launchUrl( - Uri.parse('https://angeleno.lacity.org/apps') + Uri.parse('https://sandbox.account.lacity.gov/services') ); break; case 5: await launchUrl( - Uri.parse('https://angeleno.lacity.org/help') + Uri.parse('https://sandbox.account.lacity.gov/help') ); break; case 6: @@ -214,11 +215,11 @@ class _MyHomePageState extends State { ), bottomNavigationBar: Container( padding: const EdgeInsets.all(16.0), - child: const Wrap( + child: Wrap( alignment: WrapAlignment.center, children: [ Text( - '© Copyright 2023 City of Los Angeles. ' + '© Copyright $currentYear City of Los Angeles. ' 'All rights reserved. Disclaimer | Privacy Policy', textDirection: TextDirection.ltr, textAlign: TextAlign.center, diff --git a/lib/views/screens/profile_screen.dart b/lib/views/screens/profile_screen.dart index 8d1cf37..112563c 100644 --- a/lib/views/screens/profile_screen.dart +++ b/lib/views/screens/profile_screen.dart @@ -99,186 +99,190 @@ class _ProfileScreenState extends State { children: [ Expanded( child: SingleChildScrollView( - child: Form( - key: formKey, - onChanged: () { - formKey.currentState!.save(); - }, - autovalidateMode: AutovalidateMode.disabled, - child: Column( - children: [ - const SizedBox(height: 10.0), - Row(mainAxisAlignment: MainAxisAlignment.end, - children: [ - ElevatedButton( - onPressed: (editMode && - ((user.phone!.isNotEmpty && !validPhoneNumber) || - !isFormValid) && isNotTestMode - ) ? null : () { - if (editMode) { - updateUser(); - } - setState(() { - userProvider.toggleEditing(); - }); - }, - child: Text( - editMode ? 'Save' : 'Edit' - ), - ) - ]), - const SizedBox(height: 25.0), - TextFormField( - enabled: editMode, - decoration: inputDecoration('First Name', editMode), - style: textStyle(editMode), - initialValue: user.firstName, - maxLength: 300, - maxLengthEnforcement: MaxLengthEnforcement.enforced, - keyboardType: TextInputType.name, - autovalidateMode: AutovalidateMode.onUserInteraction, - validator: (final val) { - if (val == null || val.trim().isEmpty) { - return 'Please enter a first name'; - } + child: Padding( + padding: const EdgeInsets.only(right: 15.0), + child: Form( + key: formKey, + onChanged: () { + formKey.currentState!.save(); + }, + autovalidateMode: AutovalidateMode.disabled, + child: Column( + children: [ + const SizedBox(height: 10.0), + Row(mainAxisAlignment: MainAxisAlignment.end, + children: [ + ElevatedButton( + onPressed: (editMode && + ((user.phone!.isNotEmpty && !validPhoneNumber) || + !isFormValid) && isNotTestMode + ) ? null : () { + if (editMode) { + updateUser(); + } + setState(() { + userProvider.toggleEditing(); + }); + }, + child: Text( + editMode ? 'Save' : 'Edit' + ), + ) + ] + ), + const SizedBox(height: 25.0), + TextFormField( + enabled: editMode, + decoration: inputDecoration('First Name', editMode), + style: textStyle(editMode), + initialValue: user.firstName, + maxLength: 300, + maxLengthEnforcement: MaxLengthEnforcement.enforced, + keyboardType: TextInputType.name, + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: (final val) { + if (val == null || val.trim().isEmpty) { + return 'Please enter a first name'; + } - if (!nameRegEx.hasMatch(val)) { - return 'Invalid characters in first name'; - } + if (!nameRegEx.hasMatch(val)) { + return 'Invalid characters in first name'; + } - return null; - }, - onChanged: (final val) { - setState(() { - user.firstName = val; - }); - }, - ), - const SizedBox(height: 25.0), - TextFormField( - enabled: editMode, - decoration: inputDecoration('Last Name', editMode), - style: textStyle(editMode), - initialValue: user.lastName, - maxLength: 150, - maxLengthEnforcement: MaxLengthEnforcement.enforced, - keyboardType: TextInputType.name, - autovalidateMode: AutovalidateMode.onUserInteraction, - validator: (final val) { - if (val == null || val.trim().isEmpty) { - return 'Please enter a last name'; - } + return null; + }, + onChanged: (final val) { + setState(() { + user.firstName = val; + }); + }, + ), + const SizedBox(height: 25.0), + TextFormField( + enabled: editMode, + decoration: inputDecoration('Last Name', editMode), + style: textStyle(editMode), + initialValue: user.lastName, + maxLength: 150, + maxLengthEnforcement: MaxLengthEnforcement.enforced, + keyboardType: TextInputType.name, + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: (final val) { + if (val == null || val.trim().isEmpty) { + return 'Please enter a last name'; + } - if (!nameRegEx.hasMatch(val)) { - return 'Invalid characters in last name'; - } + if (!nameRegEx.hasMatch(val)) { + return 'Invalid characters in last name'; + } - return null; - }, - onChanged: (final val) { - setState(() { - user.lastName = val; - }); - }, - ), - const SizedBox(height: 25.0), - InternationalPhoneNumberInput( - selectorConfig: const SelectorConfig( - selectorType: PhoneInputSelectorType.DIALOG, - setSelectorButtonAsPrefixIcon: true, - leadingPadding: 20.0, - ), - isEnabled: editMode, - key: const Key('phoneField'), - onInputChanged: (final PhoneNumber number) { - if (number.parseNumber().isNotEmpty) { - user.phone = number.phoneNumber!; - } else { - user.phone = ''; - } - }, - onInputValidated: (final bool value) { - if (user.phone!.isEmpty) { - setState(() { - validPhoneNumber = true; - }); - } else { - if (validPhoneNumber != value) { - setState(() { - validPhoneNumber = value; - }); - } - } - }, - autoValidateMode: isNotTestMode ? - AutovalidateMode.onUserInteraction - : AutovalidateMode.disabled, - selectorTextStyle: const TextStyle(color: Colors.black), - initialValue: PhoneNumber(phoneNumber: user.phone, isoCode: 'US'), - keyboardType: const TextInputType.numberWithOptions( - signed: true, - decimal: true - ), - ignoreBlank: true, - inputBorder: const OutlineInputBorder(), - ), - const SizedBox(height: 25.0), - TextFormField( - enabled: editMode, - decoration: inputDecoration('Address', editMode), - style: textStyle(editMode), - keyboardType: TextInputType.streetAddress, - initialValue: user.address, - onChanged: (final val) { - user.address = val; - }, - ), - const SizedBox(height: 25.0), - TextFormField( - enabled: editMode, - decoration: inputDecoration('Address 2', editMode), - style: textStyle(editMode), - keyboardType: TextInputType.streetAddress, - initialValue: user.address2, - onChanged: (final val) { - user.address2 = val; - }, - ), - const SizedBox(height: 25.0), - TextFormField( - enabled: editMode, - decoration: inputDecoration('City', editMode), - style: textStyle(editMode), - keyboardType: TextInputType.streetAddress, - initialValue: user.city, - onChanged: (final val) { - user.city = val; - }, - ), - const SizedBox(height: 25.0), - TextFormField( - enabled: editMode, - decoration: inputDecoration('State', editMode), - style: textStyle(editMode), - keyboardType: TextInputType.streetAddress, - initialValue: user.state, - onChanged: (final val) { - user.state = val; - }, - ), - const SizedBox(height: 25.0), - TextFormField( - enabled: editMode, - decoration: inputDecoration('Zip', editMode), - style: textStyle(editMode), - initialValue: user.zip, - onChanged: (final val) { - user.zip = val; - }, - keyboardType: TextInputType.number, - ), - ], - ) + return null; + }, + onChanged: (final val) { + setState(() { + user.lastName = val; + }); + }, + ), + const SizedBox(height: 25.0), + InternationalPhoneNumberInput( + selectorConfig: const SelectorConfig( + selectorType: PhoneInputSelectorType.DIALOG, + setSelectorButtonAsPrefixIcon: true, + leadingPadding: 20.0, + ), + isEnabled: editMode, + key: const Key('phoneField'), + onInputChanged: (final PhoneNumber number) { + if (number.parseNumber().isNotEmpty) { + user.phone = number.phoneNumber!; + } else { + user.phone = ''; + } + }, + onInputValidated: (final bool value) { + if (user.phone!.isEmpty) { + setState(() { + validPhoneNumber = true; + }); + } else { + if (validPhoneNumber != value) { + setState(() { + validPhoneNumber = value; + }); + } + } + }, + autoValidateMode: isNotTestMode ? + AutovalidateMode.onUserInteraction + : AutovalidateMode.disabled, + selectorTextStyle: const TextStyle(color: Colors.black), + initialValue: PhoneNumber(phoneNumber: user.phone, isoCode: 'US'), + keyboardType: const TextInputType.numberWithOptions( + signed: true, + decimal: true + ), + ignoreBlank: true, + inputBorder: const OutlineInputBorder(), + ), + const SizedBox(height: 25.0), + TextFormField( + enabled: editMode, + decoration: inputDecoration('Address', editMode), + style: textStyle(editMode), + keyboardType: TextInputType.streetAddress, + initialValue: user.address, + onChanged: (final val) { + user.address = val; + }, + ), + const SizedBox(height: 25.0), + TextFormField( + enabled: editMode, + decoration: inputDecoration('Address 2', editMode), + style: textStyle(editMode), + keyboardType: TextInputType.streetAddress, + initialValue: user.address2, + onChanged: (final val) { + user.address2 = val; + }, + ), + const SizedBox(height: 25.0), + TextFormField( + enabled: editMode, + decoration: inputDecoration('City', editMode), + style: textStyle(editMode), + keyboardType: TextInputType.streetAddress, + initialValue: user.city, + onChanged: (final val) { + user.city = val; + }, + ), + const SizedBox(height: 25.0), + TextFormField( + enabled: editMode, + decoration: inputDecoration('State', editMode), + style: textStyle(editMode), + keyboardType: TextInputType.streetAddress, + initialValue: user.state, + onChanged: (final val) { + user.state = val; + }, + ), + const SizedBox(height: 25.0), + TextFormField( + enabled: editMode, + decoration: inputDecoration('Zip', editMode), + style: textStyle(editMode), + initialValue: user.zip, + onChanged: (final val) { + user.zip = val; + }, + keyboardType: TextInputType.number, + ), + ], + ) + ) ) ) ) From 37def9e47aa4e023ee356612ddc41948efa90119 Mon Sep 17 00:00:00 2001 From: Cristian Hernandez Date: Mon, 16 Sep 2024 13:26:47 -0700 Subject: [PATCH 2/5] Fix tests. Update logout url --- lib/controllers/user_provider.dart | 2 +- test/advanced_test.dart | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/controllers/user_provider.dart b/lib/controllers/user_provider.dart index 22344b6..8ac9e55 100644 --- a/lib/controllers/user_provider.dart +++ b/lib/controllers/user_provider.dart @@ -96,7 +96,7 @@ class UserProvider extends ChangeNotifier { Future logout() => auth0Web.logout( federated: false, - returnToUrl: 'https://angeleno.lacity.org/' + returnToUrl: 'https://sandbox.account.lacity.gov/' ); User? get user => _user; diff --git a/test/advanced_test.dart b/test/advanced_test.dart index 358413b..c46e247 100644 --- a/test/advanced_test.dart +++ b/test/advanced_test.dart @@ -144,7 +144,7 @@ void main() { await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key('totpCode')), '123456'); - + await tester.pump(); await tester.tap(find.widgetWithText(TextButton, 'Finish')); await tester.pumpAndSettle(); @@ -211,6 +211,7 @@ void main() { await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key('phoneCode')), '483234'); + await tester.pump(); await tester.tap(find.widgetWithText(TextButton, 'Continue')); await tester.pumpAndSettle(); @@ -237,10 +238,12 @@ void main() { await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key('passwordField')), 'myPassword'); + await tester.pump(); await tester.tap(find.widgetWithText(TextButton, 'Continue')); await tester.pumpAndSettle(); await tester.enterText(find.byKey(const Key('phoneCode')), '483234'); + await tester.pump(); await tester.tap(find.widgetWithText(TextButton, 'Continue')); await tester.pumpAndSettle(); From 5fcaa3fb3877290ed39d5be9b846c42a895772b6 Mon Sep 17 00:00:00 2001 From: Cristian Hernandez Date: Mon, 16 Sep 2024 13:47:32 -0700 Subject: [PATCH 3/5] Changes made in Sandbox and not dev --- .env-example | 3 +++ .github/workflows/firebase-hosting-merge.yml | 1 + .github/workflows/firebase-hosting-pull-request.yml | 1 + lib/controllers/auth0_user_api.dart | 2 ++ lib/controllers/auth0_user_api_implementation.dart | 1 + lib/main.dart | 3 ++- lib/utils/constants.dart | 1 + lib/views/dialogs/mobile.dart | 3 --- 8 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.env-example b/.env-example index 2edf704..427f5d0 100644 --- a/.env-example +++ b/.env-example @@ -10,5 +10,8 @@ CLOUD_FUNCTIONS_URL= SA_EMAIL= SA_SECRET_KEY= +#Development Environment +ENVIRONMENT=development + # Places API PLACES_API_KEY= diff --git a/.github/workflows/firebase-hosting-merge.yml b/.github/workflows/firebase-hosting-merge.yml index d52354f..e628958 100644 --- a/.github/workflows/firebase-hosting-merge.yml +++ b/.github/workflows/firebase-hosting-merge.yml @@ -31,6 +31,7 @@ jobs: echo CLOUD_FUNCTIONS_URL=${{ secrets.CLOUD_FUNCTIONS_URL }} >> .env echo SA_EMAIL=${{ secrets.SA_EMAIL }} >> .env echo SA_SECRET_KEY="${{ secrets.SA_SECRET_KEY }}" >> .env + echo ENVIRONMENT="${{ secrets.ENVIRONMENT }}" >> .env - run: flutter build web --dart-define-from-file=.env - name: Update .firebaserc run: | diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index cbeb649..e591339 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -35,6 +35,7 @@ jobs: echo CLOUD_FUNCTIONS_URL=${{ secrets.CLOUD_FUNCTIONS_URL }} >> .env echo SA_EMAIL=${{ secrets.SA_EMAIL }} >> .env echo SA_SECRET_KEY="${{ secrets.SA_SECRET_KEY }}" >> .env + echo ENVIRONMENT="${{ secrets.ENVIRONMENT }}" >> .env - run: flutter build web --dart-define-from-file=.env - name: Update .firebaserc run: | diff --git a/lib/controllers/auth0_user_api.dart b/lib/controllers/auth0_user_api.dart index 6e97deb..9cd2ce8 100644 --- a/lib/controllers/auth0_user_api.dart +++ b/lib/controllers/auth0_user_api.dart @@ -17,4 +17,6 @@ abstract class Api { void confirmMFA(final Map body); void unenrollMFA(final Map body); + + void removeConnection(final String connectionId); } \ No newline at end of file diff --git a/lib/controllers/auth0_user_api_implementation.dart b/lib/controllers/auth0_user_api_implementation.dart index cdc2453..fd0277a 100644 --- a/lib/controllers/auth0_user_api_implementation.dart +++ b/lib/controllers/auth0_user_api_implementation.dart @@ -302,6 +302,7 @@ class Auth0UserApi extends Api { } } + @override Future removeConnection(final String connectionId) async { final token = await getOAuthToken(); diff --git a/lib/main.dart b/lib/main.dart index f371838..80d0048 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -26,7 +26,8 @@ class MyApp extends StatelessWidget { @override Widget build(final BuildContext context) => MaterialApp( - title: 'Angeleno - Account', + title: 'Angeleno - My Account ' + '${environment == 'prod' ? '' : ' - $environment'}', debugShowCheckedModeBanner: false, theme: ThemeData( useMaterial3: true, diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index bc64a2e..782d772 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -8,6 +8,7 @@ const cloudFunctionURL = String.fromEnvironment('CLOUD_FUNCTIONS_URL'); const serviceAccountSecret = String.fromEnvironment('SA_SECRET_KEY'); const serviceAccountEmail = String.fromEnvironment('SA_EMAIL'); +const environment = String.fromEnvironment('ENVIRONMENT'); /* Regex */ final RegExp nameRegEx = RegExp(r"^[a-zA-ZÀ-ÿ\s'\-\d]*$"); diff --git a/lib/views/dialogs/mobile.dart b/lib/views/dialogs/mobile.dart index 63c27e7..04a7c94 100644 --- a/lib/views/dialogs/mobile.dart +++ b/lib/views/dialogs/mobile.dart @@ -42,7 +42,6 @@ class _MobileDialogState extends State { String errMsg = ''; String phoneNumber = ''; - String userPassword = ''; String mfaToken = ''; String oobCode = ''; String codeProvided = ''; @@ -50,8 +49,6 @@ class _MobileDialogState extends State { bool validPhoneNumber = false; int _pageIndex = 0; - // late List dialogNext; - @override void initState() { super.initState(); From 0b3c00d00d1e16e2ae10761114566e188881f3a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:09:43 +0000 Subject: [PATCH 4/5] Bump path-to-regexp and express in /functions/auth0 Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) to 0.1.10 and updates ancestor dependency [express](https://github.com/expressjs/express). These dependencies need to be updated together. Updates `path-to-regexp` from 0.1.7 to 0.1.10 - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.7...v0.1.10) Updates `express` from 4.19.2 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: path-to-regexp dependency-type: indirect - dependency-name: express dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- functions/auth0/package-lock.json | 102 +++++++++++++++++------------- functions/auth0/package.json | 2 +- 2 files changed, 59 insertions(+), 45 deletions(-) diff --git a/functions/auth0/package-lock.json b/functions/auth0/package-lock.json index a711057..a88a7e0 100644 --- a/functions/auth0/package-lock.json +++ b/functions/auth0/package-lock.json @@ -8,7 +8,7 @@ "dependencies": { "@google-cloud/functions-framework": "^3.3.0", "axios": "^1.7.4", - "express": "^4.18.2", + "express": "^4.21.0", "firebase-admin": "^12.0.0", "firebase-functions": "^5.0.1", "jsonwebtoken": "9.0.2" @@ -2327,9 +2327,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -2339,7 +2339,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -2934,9 +2934,9 @@ "devOptional": true }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -3292,36 +3292,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -3446,12 +3446,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -5480,9 +5480,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -5732,9 +5735,12 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5898,9 +5904,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/picocolors": { "version": "1.0.1", @@ -6178,11 +6184,11 @@ "peer": true }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -6551,9 +6557,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -6573,6 +6579,14 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -6590,14 +6604,14 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" diff --git a/functions/auth0/package.json b/functions/auth0/package.json index a7d7005..e298d8b 100644 --- a/functions/auth0/package.json +++ b/functions/auth0/package.json @@ -17,7 +17,7 @@ "dependencies": { "@google-cloud/functions-framework": "^3.3.0", "axios": "^1.7.4", - "express": "^4.18.2", + "express": "^4.21.0", "firebase-admin": "^12.0.0", "firebase-functions": "^5.0.1", "jsonwebtoken": "9.0.2" From 6ab9849bf2dd942d52eb360cb74cd1e29a80bea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:09:43 +0000 Subject: [PATCH 5/5] Bump body-parser and express in /functions/auth0 Bumps [body-parser](https://github.com/expressjs/body-parser) to 1.20.3 and updates ancestor dependency [express](https://github.com/expressjs/express). These dependencies need to be updated together. Updates `body-parser` from 1.20.2 to 1.20.3 - [Release notes](https://github.com/expressjs/body-parser/releases) - [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3) Updates `express` from 4.19.2 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: body-parser dependency-type: indirect - dependency-name: express dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- functions/auth0/package-lock.json | 102 +++++++++++++++++------------- functions/auth0/package.json | 2 +- 2 files changed, 59 insertions(+), 45 deletions(-) diff --git a/functions/auth0/package-lock.json b/functions/auth0/package-lock.json index a711057..a88a7e0 100644 --- a/functions/auth0/package-lock.json +++ b/functions/auth0/package-lock.json @@ -8,7 +8,7 @@ "dependencies": { "@google-cloud/functions-framework": "^3.3.0", "axios": "^1.7.4", - "express": "^4.18.2", + "express": "^4.21.0", "firebase-admin": "^12.0.0", "firebase-functions": "^5.0.1", "jsonwebtoken": "9.0.2" @@ -2327,9 +2327,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -2339,7 +2339,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -2934,9 +2934,9 @@ "devOptional": true }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -3292,36 +3292,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -3446,12 +3446,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -5480,9 +5480,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -5732,9 +5735,12 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5898,9 +5904,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/picocolors": { "version": "1.0.1", @@ -6178,11 +6184,11 @@ "peer": true }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -6551,9 +6557,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -6573,6 +6579,14 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -6590,14 +6604,14 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" diff --git a/functions/auth0/package.json b/functions/auth0/package.json index a7d7005..e298d8b 100644 --- a/functions/auth0/package.json +++ b/functions/auth0/package.json @@ -17,7 +17,7 @@ "dependencies": { "@google-cloud/functions-framework": "^3.3.0", "axios": "^1.7.4", - "express": "^4.18.2", + "express": "^4.21.0", "firebase-admin": "^12.0.0", "firebase-functions": "^5.0.1", "jsonwebtoken": "9.0.2"