Skip to content

Commit

Permalink
Merge pull request #253 from nimblehq/feature/234-secure-storage
Browse files Browse the repository at this point in the history
  • Loading branch information
luongvo authored Aug 31, 2023
2 parents 6b4cd23 + e039988 commit fd225ca
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 18 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ All the templates can be used to kick off a new Flutter project quickly.
- [Pre-set environments](bricks/template/__brick__/%7B%7Bproject_name.snakeCase()%7D%7D#setup): `Staging` and `Production`. Environment variables are supplied through `.env` files through [flutter_config](https://pub.dev/packages/flutter_config).
- Dependency Injection (DI), State Management, and Navigating with [get_it](https://pub.dev/packages/get_it), [flutter_riverpod](https://pub.dev/packages/flutter_riverpod), and [go_router](https://pub.dev/packages/go_router).
- Networking with [dio](https://pub.dev/packages/dio) and [retrofit](https://pub.dev/packages/retrofit), JSON serializing with [json_serializable](https://pub.dev/packages/json_serializable).
- Integrated local [secure storage](https://pub.dev/packages/flutter_secure_storage).
- [Localization](https://docs.flutter.dev/accessibility-and-localization/internationalization) integrated in [3 initial languages](bricks/template/__brick__/%7B%7Bproject_name.snakeCase()%7D%7D/lib/l10n).
- [Testing](https://docs.flutter.dev/testing)-ready (unit, integration, and widget testing), [production and deployment](https://docs.flutter.dev/deployment)-ready (to Firebase, Play Store, TestFlight, and AppStore).
- Built-in [GitHub templates & CI/CD workflows](bricks/template/__brick__/%7B%7Bproject_name.snakeCase()%7D%7D/.github) integrated with GitHub Actions to perform static code analysis, test, build and deploy app builds to app distribution services or app stores.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:injectable/injectable.dart';

const _keyAccessToken = 'KEY_ACCESS_TOKEN';

abstract class SecureStorage {
Future<String?> get accessToken;

Future<void> storeAccessToken(String accessToken);

Future<void> clearAll();
}

@Singleton(as: SecureStorage)
class SecureStorageImpl extends SecureStorage {
final FlutterSecureStorage _storage;

SecureStorageImpl(this._storage);

@override
Future<String?> get accessToken => _storage.read(key: _keyAccessToken);

@override
Future<void> storeAccessToken(String accessToken) {
return _storage.write(key: _keyAccessToken, value: accessToken);
}

@override
Future<void> clearAll() {
return _storage.deleteAll();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:injectable/injectable.dart';

@module
abstract class StorageModule {
@singleton
FlutterSecureStorage get flutterSecureStorage => const FlutterSecureStorage(
aOptions: AndroidOptions(encryptedSharedPreferences: true));
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies:
flutter_localizations:
sdk: flutter
flutter_riverpod: ^2.3.6
flutter_secure_storage: ^9.0.0
flutter_svg: ^2.0.7
freezed_annotation: ^2.2.0
get_it: ^7.6.0
Expand Down
7 changes: 4 additions & 3 deletions sample/.github/workflows/android_deploy_production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
build_and_deploy_android:
name: Build & Deploy Android
runs-on: ubuntu-latest
environment: production
timeout-minutes: 30
steps:
- name: Check out
Expand All @@ -34,9 +35,9 @@ jobs:

- name: Set up .env
env:
ENV_PRODUCTION: ${{ secrets.ENV_PRODUCTION }}
ENV: ${{ secrets.ENV }}
run: |
echo $ENV_PRODUCTION > .env
echo "$ENV" > .env
# App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa
- name: Build Android apk
Expand All @@ -45,7 +46,7 @@ jobs:
- name: Deploy Android Production to Firebase
uses: wzieba/[email protected]
with:
appId: ${{ secrets.FIREBASE_ANDROID_APP_ID_PRODUCTION }}
appId: ${{ vars.FIREBASE_ANDROID_APP_ID }}
serviceCredentialsFileContent: ${{ secrets.FIREBASE_DISTRIBUTION_CREDENTIAL_JSON }}
groups: ${{ vars.FIREBASE_DISTRIBUTION_TESTER_GROUPS }}
file: build/app/outputs/flutter-apk/app-production-debug.apk
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
build_and_deploy_android:
name: Build & Deploy Android
runs-on: ubuntu-latest
environment: production
timeout-minutes: 30
steps:
- name: Check out
Expand All @@ -34,17 +35,17 @@ jobs:

- name: Set up .env
env:
ENV_PRODUCTION: ${{ secrets.ENV_PRODUCTION }}
ENV: ${{ secrets.ENV }}
run: |
echo $ENV_PRODUCTION > .env
echo "$ENV" > .env
- name: Set up release signing configs
env:
ANDROID_RELEASE_KEYSTORE_BASE64: ${{ secrets.ANDROID_RELEASE_KEYSTORE_BASE64 }}
ANDROID_SIGNING_PROPERTIES_BASE64: ${{ secrets.ANDROID_SIGNING_PROPERTIES_BASE64 }}
ANDROID_SIGNING_PROPERTIES: ${{ secrets.ANDROID_SIGNING_PROPERTIES }}
run: |
echo $ANDROID_RELEASE_KEYSTORE_BASE64 | base64 --decode > android/config/release.keystore
echo $ANDROID_SIGNING_PROPERTIES_BASE64 | base64 --decode > android/signing.properties
echo "$ANDROID_SIGNING_PROPERTIES" > android/signing.properties
- name: Build Production App Bundle
run: flutter build appbundle --flavor production --release --build-number $GITHUB_RUN_NUMBER
Expand Down
7 changes: 4 additions & 3 deletions sample/.github/workflows/android_deploy_staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
build_and_deploy_android:
name: Build & Deploy Android
runs-on: ubuntu-latest
environment: staging
timeout-minutes: 30
steps:
- name: Check out
Expand All @@ -34,9 +35,9 @@ jobs:

- name: Set up .env.staging
env:
ENV_STAGING: ${{ secrets.ENV_STAGING }}
ENV: ${{ secrets.ENV }}
run: |
echo $ENV_STAGING > .env.staging
echo "$ENV" > .env.staging
# App Bundle requires Firebase connected to Play Store to upload https://appdistribution.page.link/KPoa
- name: Build Android apk
Expand All @@ -45,7 +46,7 @@ jobs:
- name: Deploy Android Staging to Firebase
uses: wzieba/[email protected]
with:
appId: ${{ secrets.FIREBASE_ANDROID_APP_ID_STAGING }}
appId: ${{ vars.FIREBASE_ANDROID_APP_ID }}
serviceCredentialsFileContent: ${{ secrets.FIREBASE_DISTRIBUTION_CREDENTIAL_JSON }}
groups: ${{ vars.FIREBASE_DISTRIBUTION_TESTER_GROUPS }}
file: build/app/outputs/flutter-apk/app-staging-debug.apk
2 changes: 0 additions & 2 deletions sample/.github/workflows/bump_version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ jobs:
steps:
- name: Check out
uses: actions/checkout@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set new version
run: |
Expand Down
7 changes: 4 additions & 3 deletions sample/.github/workflows/ios_deploy_staging_to_firebase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
build_and_upload_staging_app_to_firebase:
name: Build And Upload iOS Staging Application To Firebase
runs-on: macOS-latest
environment: staging
env:
TEAM_ID: ${{ secrets.TEAM_ID }}
FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
Expand All @@ -18,7 +19,7 @@ jobs:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
FIREBASE_CLI_TOKEN: ${{ secrets.FIREBASE_CLI_TOKEN }}
FIREBASE_APP_ID_STAGING: ${{ secrets.FIREBASE_IOS_APP_ID_STAGING }}
FIREBASE_APP_ID: ${{ vars.FIREBASE_IOS_APP_ID }}
FIREBASE_DISTRIBUTION_TESTER_GROUPS: ${{ vars.FIREBASE_DISTRIBUTION_TESTER_GROUPS }}
GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER
steps:
Expand All @@ -41,9 +42,9 @@ jobs:

- name: Set up .env.staging
env:
ENV_STAGING: ${{ secrets.ENV_STAGING }}
ENV: ${{ secrets.ENV }}
run: |
echo $ENV_STAGING > .env.staging
echo "$ENV" > .env.staging
- name: Run code generator
run: flutter packages pub run build_runner build --delete-conflicting-outputs
Expand Down
1 change: 1 addition & 0 deletions sample/.github/workflows/ios_deploy_to_app_store.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
build_and_upload_to_app_store:
name: Build And Upload iOS Application To AppStore
runs-on: macOS-latest
environment: staging
timeout-minutes: 30
env:
TEAM_ID: ${{ secrets.TEAM_ID }}
Expand Down
1 change: 1 addition & 0 deletions sample/.github/workflows/ios_deploy_to_testflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
build_and_upload_to_testflight:
name: Build And Upload iOS Application To TestFlight
runs-on: macOS-latest
environment: staging
timeout-minutes: 30
env:
TEAM_ID: ${{ secrets.TEAM_ID }}
Expand Down
4 changes: 2 additions & 2 deletions sample/ios/fastlane/Constants/Environments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def self.FIREBASE_CLI_TOKEN
ENV['FIREBASE_CLI_TOKEN']
end

def self.FIREBASE_APP_ID_STAGING
ENV['FIREBASE_APP_ID_STAGING']
def self.FIREBASE_APP_ID
ENV['FIREBASE_APP_ID']
end

def self.FIREBASE_TESTER_GROUPS
Expand Down
2 changes: 1 addition & 1 deletion sample/ios/fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ platform :ios do
scheme_name: Constants.SCHEME_NAME_STAGING,
product_name: Constants.PRODUCT_NAME_STAGING,
bundle_id: Constants.BUNDLE_ID_STAGING,
app_id: Environments.FIREBASE_APP_ID_STAGING
app_id: Environments.FIREBASE_APP_ID
)
end

Expand Down
32 changes: 32 additions & 0 deletions sample/lib/data/local/secure_storage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:injectable/injectable.dart';

const _keyAccessToken = 'KEY_ACCESS_TOKEN';

abstract class SecureStorage {
Future<String?> get accessToken;

Future<void> storeAccessToken(String accessToken);

Future<void> clearAll();
}

@Singleton(as: SecureStorage)
class SecureStorageImpl extends SecureStorage {
final FlutterSecureStorage _storage;

SecureStorageImpl(this._storage);

@override
Future<String?> get accessToken => _storage.read(key: _keyAccessToken);

@override
Future<void> storeAccessToken(String accessToken) {
return _storage.write(key: _keyAccessToken, value: accessToken);
}

@override
Future<void> clearAll() {
return _storage.deleteAll();
}
}
9 changes: 9 additions & 0 deletions sample/lib/di/module/storage_module.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:injectable/injectable.dart';

@module
abstract class StorageModule {
@singleton
FlutterSecureStorage get flutterSecureStorage => const FlutterSecureStorage(
aOptions: AndroidOptions(encryptedSharedPreferences: true));
}
1 change: 1 addition & 0 deletions sample/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies:
flutter_localizations:
sdk: flutter
flutter_riverpod: ^2.3.6
flutter_secure_storage: ^9.0.0
flutter_svg: ^2.0.7
freezed_annotation: ^2.2.0
get_it: ^7.6.0
Expand Down

0 comments on commit fd225ca

Please sign in to comment.