diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5feb67001..47bb4ab55 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -126,7 +126,7 @@ jobs: run: make ci-android-test - name: Running workflow test for macos - run: make desktopWorkflowTest + run: make maOSWorkflowTest if: runner.os == 'macOS' timeout-minutes: 60 diff --git a/Makefile b/Makefile index 3192ce252..ea0c120d2 100644 --- a/Makefile +++ b/Makefile @@ -800,10 +800,16 @@ windowsDesktopTest: sh $(CURDIR)/integration_test/run_windows_test.sh # Run specific tests on desktop +#you can pass DEVICE= (e.g., macOS, linux, windows) runDesktopTest: @ARGUMENTS=$(filter-out $@,$(MAKECMDGOALS)); \ + DEVICE=$(DEVICE); \ + if [ -z "$$DEVICE" ]; then \ + echo "Error: DEVICE is not specified. Use DEVICE= (e.g., macOS, linux, android)"; \ + exit 1; \ + fi; \ echo "Running tests on: $$ARGUMENTS" && \ - flutter test $$ARGUMENTS -d macOS -r expanded + flutter test $$ARGUMENTS -d $$DEVICE -r expanded # Run all android test on Firebase test lab diff --git a/README.md b/README.md index 69cd9aa70..59f4d24a5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Lantern App [![Go Actions Status](https://github.com/getlantern/android-lantern/actions/workflows/go.yml/badge.svg)](https://github.com/getlantern/android-lantern/actions) [![Coverage Status](https://coveralls.io/repos/github/getlantern/android-lantern/badge.svg?t=C4SaZX)](https://coveralls.io/github/getlantern/android-lantern) -Lantern APP is an app that uses the [VpnService](https://developer.android.com/reference/android/net/VpnService) API to intercept and reroute all device traffic to the Lantern circumvention tool. +Lantern APP is an app that uses +the [VpnService](https://developer.android.com/reference/android/net/VpnService) API to intercept +and reroute all device traffic to the Lantern circumvention tool. ## Feature: Replica Mobile @@ -8,88 +10,104 @@ See [docs/replica.md](docs/replica.md). ## Acknowledgements -This application uses ringtone sounds from Mike Koenig available [here](https://soundbible.com/1868-Ringing-Phone.html) -and licensed under the [Creative Commons Attribution License](https://creativecommons.org/licenses/by/3.0/). +This application uses ringtone sounds from Mike Koenig +available [here](https://soundbible.com/1868-Ringing-Phone.html) +and licensed under +the [Creative Commons Attribution License](https://creativecommons.org/licenses/by/3.0/). ## Code Generation + This project includes various pieces of autogenerated code like protocol buffers and routes. All of this code can be generated by running `make codegen` or just `make`. Specific pieces of code can be generated per the below instructions. ### Protocol Buffers + If you update the protocol buffer definitions in protos_shared, make sure to run `make protos` to update the generated dart code. -Note - you might see an error like `Can't load Kernel binary: Invalid SDK hash.`. It seems that one can ignore this. +Note - you might see an error like `Can't load Kernel binary: Invalid SDK hash.`. It seems that one +can ignore this. ## Building and Releasing ### Dependencies -All these dependencies must be in your PATH. Some of this is Android specific, see below for other platforms. +All these dependencies must be in your PATH. Some of this is Android specific, see below for other +platforms. * Java 11 or greater -* [Android Studio](https://developer.android.com/studio?_gl=1*1wowe6v*_up*MQ..&gclid=Cj0KCQjw6auyBhDzARIsALIo6v-bn0juONfkfmQAJtwssRCQWADJMgGfRBisMNTSXHt5CZnyZVSK2Y8aAgCmEALw_wcB&gclsrc=aw.ds) (Android Studio Jellyfish | 2023.3.1 Patch 1) +* [Android Studio](https://developer.android.com/studio?_gl=1*1wowe6v*_up*MQ..&gclid=Cj0KCQjw6auyBhDzARIsALIo6v-bn0juONfkfmQAJtwssRCQWADJMgGfRBisMNTSXHt5CZnyZVSK2Y8aAgCmEALw_wcB&gclsrc=aw.ds) ( + Android Studio Jellyfish | 2023.3.1 Patch 1) * [Xcode](https://developer.apple.com/xcode/resources/) * [Git](https://git-scm.com/downloads) * [Android NDK](#steps-to-run-the-project) - * NDK should be version 26.x, for example 26.0.10792818. + * NDK should be version 26.x, for example 26.0.10792818. * [Git LFS](https://git-lfs.github.com) - - more information in [Usage](#usage) + - more information in [Usage](#usage) * [Flutter (3.24.0)](https://flutter.dev) * [sentry-cli](https://docs.sentry.io/product/cli/installation/) - - This is used for uploading native debug symbols to Sentry + - This is used for uploading native debug symbols to Sentry * [gomobile](https://github.com/golang/go/wiki/Mobile#tools) * [json-server](https://github.com/typicode/json-server) - * Only necessary for testing Replica + * Only necessary for testing Replica * CMake 3.22.1 - * You can get this from Android SDK Manager + * You can get this from Android SDK Manager * [CocoaPods](https://cocoapods.org/) - * Possibly this is only needed on Apple platforms. + * Possibly this is only needed on Apple platforms. * Linux - * [libayatana-appindicator](https://github.com/AyatanaIndicators/libayatana-appindicator) (required by [tray_manager](https://github.com/leanflutter/tray_manager#linux-requirements)) - * [gstreamer](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html) (required by [flutter plugin audioplayers](https://pub.dev/packages/audioplayers_linux)) - * [libclang-dev](https://apt.llvm.org) (required by [ffigen](https://pub.dev/packages/ffigen)) + * [libayatana-appindicator](https://github.com/AyatanaIndicators/libayatana-appindicator) ( + required by [tray_manager](https://github.com/leanflutter/tray_manager#linux-requirements)) + * [gstreamer](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html) ( + required by [flutter plugin audioplayers](https://pub.dev/packages/audioplayers_linux)) + * [libclang-dev](https://apt.llvm.org) (required by [ffigen](https://pub.dev/packages/ffigen)) ### ๐Ÿš€ Setup Project: * Install all prerequisites * Run `git submodule update --init --recursive` * Run `git lfs install && git pull`. -* Put the [app.env](https://my.1password.com/app#/everything/AllItems/whdjlkyj7ku6pumtyc7nh5vg4yadqasjh2hspgjgvgfllyekhcrq) file (Frontend vault) from 1Password in the repo root. +* Put + the [app.env](https://my.1password.com/app#/everything/AllItems/whdjlkyj7ku6pumtyc7nh5vg4yadqasjh2hspgjgvgfllyekhcrq) + file (Frontend vault) from 1Password in the repo root. * Go to the **SDK MANAGER** * Select **Android SDK** * Check the SDK from android 5.0(LOLLIPOP) up to the Latest Version at the moment. * Go to **SDK Tools** and check the option **Show Package Details** -* On the Android SDK Build-Tools, check from: SDK 30 up to the latest at the moment. (is optional if you wish to add more SDK alternatives such as 27.0, 28 or 29). +* On the Android SDK Build-Tools, check from: SDK 30 up to the latest at the moment. (is optional if + you wish to add more SDK alternatives such as 27.0, 28 or 29). * On the NDK(Side by side) check the latest version of 22.x (not anything newer) * Make sure that you have the latest **Android SDK Command-line Tools** * Finally select the following: - - Android Emulator - - Android SDK Platform-Tools - - Google play APK Expansion Library - - Google play Instant Development SDK - - Google Play Licensing Library - - Google Play Services - - Intel x86 Emulator Accelerator (HAXM installer) + - Android Emulator + - Android SDK Platform-Tools + - Google play APK Expansion Library + - Google play Instant Development SDK + - Google Play Licensing Library + - Google Play Services + - Intel x86 Emulator Accelerator (HAXM installer) * Click on Apply and accept the Terms and Conditions. * Open Xcode first time open Xcode and install necessary components -* Download Certificate and provisioning profile from 1Pass [Search [IOS Certificates and profiles](https://my.1password.com/vaults/all/allitems)] +* Download Certificate and provisioning profile from + 1Pass [Search [IOS Certificates and profiles](https://my.1password.com/vaults/all/allitems)] * Lastly `Flutter Doctor` to confirm that your setup is correct and ready! ### ๐Ÿค– Running the project on Android -* `make android-lib ANDROID_ARCH` (you need to generated liblantern-all.aar containing the Go backend code in order for the project to compile.) +* `make android-lib ANDROID_ARCH` (you need to generated liblantern-all.aar containing the Go + backend code in order for the project to compile.) * `flutter pub get` * `flutter run --flavor prod` ### ๐Ÿ Running the project on iOS -* `make build-framework` (you need to generated Internalsdk.xcframework. containing the Go backend code in order for the project to compile.) +* `make build-framework` (you need to generated Internalsdk.xcframework. containing the Go backend + code in order for the project to compile.) * `flutter pub get` * `flutter run --flavor prod` -**Note**: If you're using an M1 or M2 chip, navigate to the ios folder and run `arch -x86_64 pod install` +**Note**: If you're using an M1 or M2 chip, navigate to the ios folder and +run `arch -x86_64 pod install` ### ๐Ÿ’ป Running the Project on Desktop @@ -117,19 +135,23 @@ You can easily run emulators directly from the command line with the following: ### ๐Ÿ‘ฉโ€๐Ÿ’ป Using Android Studio? No problem! -We've got you covered! If you prefer using Android Studio, we have already set up the configuration files for you. Just select the prod configuration and hit Run... Get ready to start digging! ๐Ÿ˜„๐Ÿ” +We've got you covered! If you prefer using Android Studio, we have already set up the configuration +files for you. Just select the prod configuration and hit Run... Get ready to start digging! ๐Ÿ˜„๐Ÿ” -You can build an emulator with `./scripts/run_avd.rb`. Here's an example run: `./scripts/run_avd.rb --level=30 --abi=x86 --use_google_apis --window`. +You can build an emulator with `./scripts/run_avd.rb`. Here's an example +run: `./scripts/run_avd.rb --level=30 --abi=x86 --use_google_apis --window`. You'll need Ruby >= 2.3 installed and `colorize` gem (i.e., `gem install colorize`). [//]: # (#### Flutter Logging) [//]: # () + [//]: # (The Flutter component uses [logger](https://pub.dev/packages/logger) package for logging.) [//]: # (See `home.dart#build()` to know where it's configured.) [//]: # () + [//]: # (During development, you'll notice a lot of `GoLog`-tagged code. Feel-free to comment that out during your flutter work.) [//]: # (A sane terminal command (using [pidcat](https://github.com/JakeWharton/pidcat)) is `pidcat org.getlantern.lantern -i GoLog -i System.out -w 3`.) @@ -137,27 +159,33 @@ You'll need Ruby >= 2.3 installed and `colorize` gem (i.e., `gem install coloriz ### Building the InternalSdk (AKA Lantern Core) as a library The core Lantern functionality is written in Go and lives in `./internalsdk`. -It is compiled from Go using [Gomobile](https://github.com/golang/mobile) to appropriate formats for each platform. +It is compiled from Go using [Gomobile](https://github.com/golang/mobile) to appropriate formats for +each platform. #### Android + * To generate AAR run `make android-lib ANDROID_ARCH=all` * For compiled code lives in `./android/app/libs` and is called `liblantern-ARCH.aar`. #### IOS + * To generate XCodeFramework run `make build-framework` For compiled code lives in `./ios/internalsdk/` and is called `Internalsdk.xcframework`. #### Desktop + The desktop app lives under `desktop` .. To build the Go shared library on macOS: -* To build for desktop `make darwin` for macOS, `make windows` for Windows, and `make linux-amd64` for Linux. +* To build for desktop `make darwin` for macOS, `make windows` for Windows, and `make linux-amd64` + for Linux. * Generate the FFI bindings `make ffigen` [//]: # (#### Testing against Lantern's staging servers) [//]: # () + [//]: # (Package the AAR with `make android-lib ANDROID_ARCH=all STAGING=true`) ### Making Android debug builds (Not yet implemented on IOS) @@ -183,10 +211,13 @@ make android-release-install [//]: # (### ๐Ÿšง Making Staging Builds) [//]: # () + [//]: # () + [//]: # (To build mobile for staging, use the STAGING command line argument:) [//]: # () + [//]: # (```) [//]: # (STAGING=true make android-debug android-install) @@ -194,6 +225,7 @@ make android-release-install [//]: # (```) [//]: # () + [//]: # (This will build Flashlight with the same [STAGING flag](https://github.com/getlantern/flashlight/v7/blob/9eb8abbe036e86b9e72a1a938f29e59f75391676/common/const.go#L43), which allows your client to use the [staging pro-server](https://github.com/getlantern/pro-server-neu/blob/fa2859edf213998e15cd7c00461e52fd97a9e570/README.md#L125) instance instead of the production one.) ### ๐ŸŽ‰ Making Release Builds @@ -201,23 +233,29 @@ make android-release-install #### IOS Do this to make a release build: + ``` VERSION=x.x.x make ios-release ``` + **Note**: Replace x.x.x with the version number of your release. This will + - Set the version number in the info.plist file and increment the build number 1 - Upload the DSYM file to Sentry - Open the build folder once the build is complete - #### Android -The Android app is distributed in two ways, as an APK for side-loaded installation and as an app bundle (aab) for distribution on the Google Play Store. The APKs are architecture specific whereas the app bundle contains all 4 architectures (arm and x86 in 32-bit and 64-bit variants). + +The Android app is distributed in two ways, as an APK for side-loaded installation and as an app +bundle (aab) for distribution on the Google Play Store. The APKs are architecture specific whereas +the app bundle contains all 4 architectures (arm and x86 in 32-bit and 64-bit variants). Do this to make a release build: -- Make sure `./android/local.properties` exists. If not, create it to look like this (Replace with your own values. Find `flutter.sdk` by running `flutter doctor -v`): +- Make sure `./android/local.properties` exists. If not, create it to look like this (Replace with + your own values. Find `flutter.sdk` by running `flutter doctor -v`): ``` sdk.dir=/Users/AwesomeLanternDev/Library/Android/sdk @@ -225,20 +263,29 @@ Do this to make a release build: ``` - Download [sentry-cli](https://docs.sentry.io/product/cli/installation/) - - Authenticate with [these credentials](https://my.1password.com/vaults/all/allitems/npsu55phkvbytbomlhnfuhqcii) by running `sentry-cli login`. You need this, else the Makefile task will fail -- Download [this release keystore](https://my.1password.com/vaults/all/allitems/rp5dzcli5ghilzfsanajwz6nqm) file and put it somewhere like `/tmp/mykeystore,jks` -- Replace `~/.gradle/gradle.properties` with the values found [here](https://my.1password.com/vaults/all/allitems/jq67eb556b44gb6nlfjm2yh3tq) - - Make sure to replace `KEYSTORE_FILE` with the location of your keystore (`/tmp/mykeystore,jks` in our case above) + - Authenticate + with [these credentials](https://my.1password.com/vaults/all/allitems/npsu55phkvbytbomlhnfuhqcii) + by running `sentry-cli login`. You need this, else the Makefile task will fail +- +Download [this release keystore](https://my.1password.com/vaults/all/allitems/rp5dzcli5ghilzfsanajwz6nqm) +file and put it somewhere like `/tmp/mykeystore,jks` +- Replace `~/.gradle/gradle.properties` with the values + found [here](https://my.1password.com/vaults/all/allitems/jq67eb556b44gb6nlfjm2yh3tq) + - Make sure to replace `KEYSTORE_FILE` with the location of your keystore (`/tmp/mykeystore,jks` + in our case above) - Run `VERSION= make android-release ANDROID_ARCH=all` - - Or, `DEVELOPMENT_MODE=true make android-release ANDROID_ARCH=all` to enable "Development Mode" which has extra dev features like taking screenshots and dev settings. + - Or, `DEVELOPMENT_MODE=true make android-release ANDROID_ARCH=all` to enable "Development Mode" + which has extra dev features like taking screenshots and dev settings. ### ๐Ÿ“ฆ Building Release Packages and Distributing the App -Lantern-client release and beta packages are built using Continuous Integration (CI). You can create installers for beta, production, or internal testing by adjusting the tag syntax. +Lantern-client release and beta packages are built using Continuous Integration (CI). You can create +installers for beta, production, or internal testing by adjusting the tag syntax. #### Production Release for All Platforms ๐ŸŒ -To release the production version for all platforms (including Android, iOS, and macOS), use the following command: +To release the production version for all platforms (including Android, iOS, and macOS), use the +following command: `git tag -a "lantern-7.0.0" -f -m "Tagging production release"` @@ -250,7 +297,6 @@ Finally, to create an internal build, use "internal", as in: `git tag -a "lantern-7.0.0-internal" -f -m "Tagging internal release"` - #### Platform-Specific Releases ๐Ÿ“ฑ๐Ÿ’ป For releasing to specific platforms, use the appropriate prefix: @@ -271,24 +317,33 @@ After creating a tag, push it to GitHub to trigger the CI/CD pipeline: `git push origin [TAG-NAME]`or `git push origin lantern-7.0.0` -You can then find all built binaries in the [lantern-binaries repository](https://github.com/getlantern/lantern-binaries). +You can then find all built binaries in +the [lantern-binaries repository](https://github.com/getlantern/lantern-binaries). -To publish a release on Google Play, go to the Lantern App on the [Google Play Console](https://play.google.com/console/u/0/developers/4642290275832863621/app/4973965144252805146/app-dashboard?timespan=thirtyDays) and create a new release using the [app bundle](lantern-installer.aab). +To publish a release on Google Play, go to the Lantern App on +the [Google Play Console](https://play.google.com/console/u/0/developers/4642290275832863621/app/4973965144252805146/app-dashboard?timespan=thirtyDays) +and create a new release using the [app bundle](lantern-installer.aab). ### Enabling Auto-Update for a Sideloaded Release -Just because something's been released to prod doesn't mean clients will auto-update, there's an additional step for that. The below will release the current production version to autoupdate. Please make sure the VERSION parameter matches the current production version. +Just because something's been released to prod doesn't mean clients will auto-update, there's an +additional step for that. The below will release the current production version to autoupdate. +Please make sure the VERSION parameter matches the current production version. ``` GH_TOKEN= VERSION=7.2.0 make auto-updates ``` -To find the latest version that's been set for auto updates, check the [lantern](https://github.com/getlantern/lantern/releases) repo. +To find the latest version that's been set for auto updates, check +the [lantern](https://github.com/getlantern/lantern/releases) repo. -You can obtain the GH_TOKEN for releasing auto-updates from [1Password](https://start.1password.com/open/i?a=HHU7O6L7H5E33C6UDFD6Q3SYH4&v=nupvcrpazomdrozlmemsywqfj4&i=qlxf7ffkjnhu7nqkshvwi7ocpm&h=lantern.1password.com). +You can obtain the GH_TOKEN for releasing auto-updates +from [1Password](https://start.1password.com/open/i?a=HHU7O6L7H5E33C6UDFD6Q3SYH4&v=nupvcrpazomdrozlmemsywqfj4&i=qlxf7ffkjnhu7nqkshvwi7ocpm&h=lantern.1password.com). ### Testing Auto-Update with release builds -Sometimes you may need to make a release build with an old version that is eligible for auto-update. You can do that by using the VERSION_CODE environment variable + +Sometimes you may need to make a release build with an old version that is eligible for auto-update. +You can do that by using the VERSION_CODE environment variable ``` APP=lantern VERSION_CODE=1 VERSION=1.0.0 make android-release @@ -331,16 +386,25 @@ SECRETS_DIR=$PATH_TO_TOO_MANY_SECRETS VERSION=2.0.0-beta1 make android-bundle ``` ## ๐Ÿงช Testing -For testing we are using [patrol](https://pub.dev/packages/patrol) framework, Patrol simplifies interaction with the native layer and offers an extensive set of easy-to-use testing APIs. + +For testing we are using [patrol](https://pub.dev/packages/patrol) framework, Patrol simplifies +interaction with the native layer and offers an extensive set of easy-to-use testing APIs. ### Integration Testing #### Writing Integration Testing -* Always use our custom [patrol](https://github.com/getlantern/lantern-client/blob/d5c36eba30e8072c0327eca4eea8472cbfa49cb5/integration_test/utils/test_utils.dart#L54) method for writing any new integration tests. Similarly, utilize [appTearDown](https://github.com/getlantern/lantern-client/blob/d5c36eba30e8072c0327eca4eea8472cbfa49cb5/integration_test/utils/test_utils.dart#L95) for cleanup. These methods ensure compatibility across different environments for mobile and desktop platforms. -* Structure tests to simulate real user flows, such as changing app settings (e.g., language preferences) or completing actions -* Ensure tests are compatible with all supported platforms (mobile and desktop). -* If mocks are necessary for specific scenarios, ensure they are clearly documented and cover all critical edge cases. +* Always use our + custom [patrol](https://github.com/getlantern/lantern-client/blob/d5c36eba30e8072c0327eca4eea8472cbfa49cb5/integration_test/utils/test_utils.dart#L54) + method for writing any new integration tests. Similarly, + utilize [appTearDown](https://github.com/getlantern/lantern-client/blob/d5c36eba30e8072c0327eca4eea8472cbfa49cb5/integration_test/utils/test_utils.dart#L95) + for cleanup. These methods ensure compatibility across different environments for mobile and + desktop platforms. +* Structure tests to simulate real user flows, such as changing app settings (e.g., language + preferences) or completing actions +* Ensure tests are compatible with all supported platforms (mobile and desktop). +* If mocks are necessary for specific scenarios, ensure they are clearly documented and cover all + critical edge cases. #### Running Integration Testing @@ -348,48 +412,60 @@ For testing we are using [patrol](https://pub.dev/packages/patrol) framework, Pa * Make sure to connect any device or emulator to run the test. To run all integration the test on mobile + ```sh make appWorkflowTest ``` To run and single test on mobile + ```sh make runTest testfile or make runTest integration_test/app_startup_flow_test.dart ``` To run all integration the test on desktop + ```sh make desktopWorkflowTest ``` -To run and single test on dekstop +To run and single test on desktop +You need pass DEVICE=macOS or DEVICE=windows or DEVICE=linux + ```sh -make runDesktopTest testfile or integration_test/app_startup_flow_test.dart +make integration_test/app_startup_flow_test.dart DEVICE=macOD ``` #### Running Test on Firebase Test Lab ##### Setup -* Install `gcloud CLI`. If not, you can install it by following the instructions [here](https://cloud.google.com/sdk/docs/install). + +* Install `gcloud CLI`. If not, you can install it by following the + instructions [here](https://cloud.google.com/sdk/docs/install). * Login to your Google Cloud account by running `gcloud auth login`. * Set the project ID by running `gcloud config set project lantern-android`. - #### Running the test + To Run test on android device on Firebase Test Lab, you need to run the following command: + ```sh make ci-android-test ``` #### Testing Replica -A few Replica tests run [json-server](https://github.com/typicode/json-server) to serve dummy data during tests instead of hitting an actual Replica instance. -The tests should transparently setup and teardown the dummy server but you need to have `json-server` in your PATH. + +A few Replica tests run [json-server](https://github.com/typicode/json-server) to serve dummy data +during tests instead of hitting an actual Replica instance. +The tests should transparently setup and teardown the dummy server but you need to +have `json-server` in your PATH. ### Java/Kotlin * For testing all `android/app/src/test` tests, run `./gradlew :app:test` * For testing all `android/app/src/androidTest` tests, run `./gradlew :app:connectedAndroidTest` -* For testing a specific an `androidTest` test, easiest is to open that file in Android Studio and clicking on the green play button next to the test +* For testing a specific an `androidTest` test, easiest is to open that file in Android Studio and + clicking on the green play button next to the test * For testing the internalsdk package, run `cd ./internalsdk && go test ./...` ### Unit Test Graph @@ -397,15 +473,21 @@ The tests should transparently setup and teardown the dummy server but you need If you wanna visualize the current percentage of code coverage you need to do the following steps. 1. On your `terminal` check if you have installed: `lcov` if not then install. -2. Go to on your terminal `android-lantern/coverage` and type: `genhtml coverage/lcov.info -o coverage/html` that will generate a nice html file with the code coverage of all your files. +2. Go to on your terminal `android-lantern/coverage` and + type: `genhtml coverage/lcov.info -o coverage/html` that will generate a nice html file with the + code coverage of all your files. ## Testing Google Play Payments -If you're trying to test Google Play Payments with a sideloaded build, you will need to satisfy one of the following conditions, otherwise you'll get an error saying "the item you requested is not available for purchase" +If you're trying to test Google Play Payments with a sideloaded build, you will need to satisfy one +of the following conditions, otherwise you'll get an error saying "the item you requested is not +available for purchase" when trying to purchase in-app. -A. Your login for the Google Play Store needs to be a License Tester for our account, as described [here](https://stackoverflow.com/a/55329990) -B. Alternately, you can also try to follow [these steps](https://stackoverflow.com/a/18172192) to make sure that the build is known to Google, but this didn't work for me. +A. Your login for the Google Play Store needs to be a License Tester for our account, as +described [here](https://stackoverflow.com/a/55329990) +B. Alternately, you can also try to follow [these steps](https://stackoverflow.com/a/18172192) to +make sure that the build is known to Google, but this didn't work for me. ``` Make sure to upload the signed APK to developer console. @@ -426,24 +508,35 @@ B. Alternately, you can also try to follow [these steps](https://stackoverflow.c ## Testing Freekassa Payments -You'd most probably wanna run this against Lantern's staging servers **and** turn on testing mode for Freekassa. Unfortunately in Freekassa, once you turn on `Testing Mode`, you can't switch back without affecting live payments. Ideally, contant Freekassa support to see how you can enable a separate testing mode. I'll just mention here some helpful notes while testing Freekassa before we went live with it. - -- Building the Flashlight library (i.e., `internalsdk`) with `make android-lib ANDROID_ARCH=all STAGING=true` is tempting, but it's not gonna work since all staging proxies you'll use (i.e., `fallback-*` proxies did not work at all for me as of today <25-12-2022, soltzen>). - - You'll need to do the incredibly-hacky approach of modifying this function `LanternHttpClient:createProUrl`: - - public static HttpUrl createProUrl(final String uri, final Map params) { - // final String url = String.format("http://localhost/pro%s", uri); - final String url = String.format("https://api-staging.getiantem.org%s", uri); - HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder(); - if (params != null) { - for (Map.Entry param : params.entrySet()) { - builder.addQueryParameter(param.getKey(), param.getValue()); - } - } - return builder.build(); - } - -- You can debug pro-server-neu's staging instance (i.e., `api-staging.getiantem.org`) using a combination of log, telemetry and checking the staging Redis instance (see [here](https://github.com/getlantern/pro-server-neu/blob/c79c1b8da9e418bc4b075392fde9b051c699141d/README.md?plain=1#L125) for more info) +You'd most probably wanna run this against Lantern's staging servers **and** turn on testing mode +for Freekassa. Unfortunately in Freekassa, once you turn on `Testing Mode`, you can't switch back +without affecting live payments. Ideally, contant Freekassa support to see how you can enable a +separate testing mode. I'll just mention here some helpful notes while testing Freekassa before we +went live with it. + +- Building the Flashlight library (i.e., `internalsdk`) + with `make android-lib ANDROID_ARCH=all STAGING=true` is tempting, but it's not gonna work since + all staging proxies you'll use (i.e., `fallback-*` proxies did not work at all for me as of + today <25-12-2022, soltzen>). + - You'll need to do the incredibly-hacky approach of modifying this + function `LanternHttpClient:createProUrl`: + + public static HttpUrl createProUrl(final String uri, final Map params) { + // final String url = String.format("http://localhost/pro%s", uri); + final String url = String.format("https://api-staging.getiantem.org%s", uri); + HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder(); + if (params != null) { + for (Map.Entry param : params.entrySet()) { + builder.addQueryParameter(param.getKey(), param.getValue()); + } + } + return builder.build(); + } + +- You can debug pro-server-neu's staging instance (i.e., `api-staging.getiantem.org`) using a + combination of log, telemetry and checking the staging Redis instance ( + see [here](https://github.com/getlantern/pro-server-neu/blob/c79c1b8da9e418bc4b075392fde9b051c699141d/README.md?plain=1#L125) + for more info) ## Running Appium tests locally @@ -463,10 +556,13 @@ appium driver install --source=npm appium-flutter-driver appium driver install espresso ``` -3. Generate a debug build with `CI=true make android-debug ANDROID_ARCH=all` ... CI needs to be set to true to enable the +3. Generate a debug build with `CI=true make android-debug ANDROID_ARCH=all` ... CI needs to be set + to true to enable the Flutter driver extension. -4. Modify [local_config.json](appium_kotlin/app/src/test/resources/local/local_config.json) to specify the path of a debug build APK on your system, and change `appium:udid` to specify your device ID (you can get this from `adb devices`) +4. Modify [local_config.json](appium_kotlin/app/src/test/resources/local/local_config.json) to + specify the path of a debug build APK on your system, and change `appium:udid` to specify your + device ID (you can get this from `adb devices`) 5. Make sure your device is connected to your computer and then run @@ -482,6 +578,7 @@ To run a specific test, you can do ``` ## Source Dump + Lantern Android source code is made available via source dump tarballs. To create one, run: ``` @@ -490,14 +587,18 @@ VERSION=2.0.0 make sourcedump This will create a file `lantern-android-sources-2.0.0.tar.gz`. -This tarball deliberately excludes UI resources like images and localized strings. It also deliberately excludes 3rd party Java libraries from the libs folder. +This tarball deliberately excludes UI resources like images and localized strings. It also +deliberately excludes 3rd party Java libraries from the libs folder. -The tarball does include vendored Go libraries, including all of the getlantern.org Go libraries. In this tarball, these are all licensed under the GPL +The tarball does include vendored Go libraries, including all of the getlantern.org Go libraries. In +this tarball, these are all licensed under the GPL as explained in [LICENSING.md](LICENSING.md). -All embedded URL literals in the getlantern.org Go code are elided to make it harder for clones to build a working version of Lantern. +All embedded URL literals in the getlantern.org Go code are elided to make it harder for clones to +build a working version of Lantern. -TODO: once we're confident these are working well, we should automate the upload of these to S3 and GitHub along with the upload of releases. +TODO: once we're confident these are working well, we should automate the upload of these to S3 and +GitHub along with the upload of releases. ## Known issues when building the project @@ -511,12 +612,15 @@ TODO: once we're confident these are working well, we should automate the upload Restart your computer. **Android Studio tries to access proxy server** -If you're running Lantern when you start Android Studio, and then turn off Lantern, Android Studio will keep trying to access resources via the proxy (which is no longer running). +If you're running Lantern when you start Android Studio, and then turn off Lantern, Android Studio +will keep trying to access resources via the proxy (which is no longer running). To fix this, restart Android Studio. ## VSCode configurations -If you like that VSCode start running the project without the need of be constantly typing the command. +If you like that VSCode start running the project without the need of be constantly typing the +command. + - Create a folder on the root of your project named: `.vscode` - Inside .vscode create a file named: `launch.json` - Add the following inside `launch.json` @@ -525,7 +629,7 @@ If you like that VSCode start running the project without the need of be constan { "version": "0.2.0", "configurations": [ - { + { "name": "Debug", "program": "lib/main.dart", "request": "launch", @@ -534,7 +638,7 @@ If you like that VSCode start running the project without the need of be constan "args": [ "--no-sound-null-safety", "--flavor", - "prod", + "prod" ] } ] @@ -543,12 +647,13 @@ If you like that VSCode start running the project without the need of be constan ## Linting -This project is formatted and linted with ktlint using the [ktlint-gradle plugin](https://github.com/JLLeitschuh/ktlint-gradle). +This project is formatted and linted with ktlint using +the [ktlint-gradle plugin](https://github.com/JLLeitschuh/ktlint-gradle). -You can install the [ktlint Intellij plugin](https://plugins.jetbrains.com/plugin/15057-ktlint-unofficial-) +You can install +the [ktlint Intellij plugin](https://plugins.jetbrains.com/plugin/15057-ktlint-unofficial-) for some support for linting within Android Studio. - ### Add Commit Hook ``` @@ -557,7 +662,6 @@ for some support for linting within Android Studio. This adds a pre commit hook that lints all staged files upon commit. - ### Manually Auto-format ``` @@ -566,7 +670,6 @@ This adds a pre commit hook that lints all staged files upon commit. This auto-formats all Kotlin files in the project. - ### Manually Check ``` @@ -579,7 +682,9 @@ This manually runs the linter against all Kotlin files in the project. ### Why is there a long-running notification? -We run Lantern as a foreground service so that it remains on and connected with our messaging server. Typical Android applications use Google Play Services for push notifications, so they don't have have to maintain this kind of connection themselves. +We run Lantern as a foreground service so that it remains on and connected with our messaging +server. Typical Android applications use Google Play Services for push notifications, so they don't +have have to maintain this kind of connection themselves. We can't use Google Play Services because: diff --git a/integration_test/run_macos_test.sh b/integration_test/run_macos_test.sh index d04ffeab5..23be633d9 100644 --- a/integration_test/run_macos_test.sh +++ b/integration_test/run_macos_test.sh @@ -1,8 +1,24 @@ # Find all _test.dart files in the integration_test directory and its immediate subdirectories + +all_tests_passed=true + +# Find all _test.dart files and iterate over them find integration_test -maxdepth 4 -type f -name '*_test.dart' | while read test_file; do - flutter test "$test_file" -d macOS + echo "Running test: $test_file" + flutter test "$test_file" -d macOS -r github if [ $? -ne 0 ]; then echo "Test $test_file failed." - exit 1 + all_tests_passed=false + else + echo "Test $test_file passed." fi done + +# Fail the script if any test failed +if [ "$all_tests_passed" = false ]; then + echo "One or more tests failed." + exit 1 +else + echo "All tests passed successfully." + exit 0 +fi diff --git a/internalsdk/protos/vpn.pb.go b/internalsdk/protos/vpn.pb.go index e0a3fcebb..208f751f0 100644 --- a/internalsdk/protos/vpn.pb.go +++ b/internalsdk/protos/vpn.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.33.0-devel // protoc v5.28.3 // source: protos_shared/vpn.proto @@ -88,10 +88,11 @@ type Bandwidth struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Percent int64 `protobuf:"varint,1,opt,name=percent,proto3" json:"percent,omitempty"` // [0, 100] - MibUsed int64 `protobuf:"varint,2,opt,name=mibUsed,proto3" json:"mibUsed,omitempty"` // in MB - MibAllowed int64 `protobuf:"varint,3,opt,name=mibAllowed,proto3" json:"mibAllowed,omitempty"` // in MB - TtlSeconds int64 `protobuf:"varint,4,opt,name=ttlSeconds,proto3" json:"ttlSeconds,omitempty"` // number of seconds left before data reset + Percent int64 `protobuf:"varint,1,opt,name=percent,proto3" json:"percent,omitempty"` // [0, 100] + MibUsed int64 `protobuf:"varint,2,opt,name=mibUsed,proto3" json:"mibUsed,omitempty"` // in MB + MibAllowed int64 `protobuf:"varint,3,opt,name=mibAllowed,proto3" json:"mibAllowed,omitempty"` // in MB + TTLSeconds int64 `protobuf:"varint,4,opt,name=TTLSeconds,proto3" json:"TTLSeconds,omitempty"` // number of seconds left before data reset + AsOf string `protobuf:"bytes,5,opt,name=AsOf,proto3" json:"AsOf,omitempty"` } func (x *Bandwidth) Reset() { @@ -147,13 +148,20 @@ func (x *Bandwidth) GetMibAllowed() int64 { return 0 } -func (x *Bandwidth) GetTtlSeconds() int64 { +func (x *Bandwidth) GetTTLSeconds() int64 { if x != nil { - return x.TtlSeconds + return x.TTLSeconds } return 0 } +func (x *Bandwidth) GetAsOf() string { + if x != nil { + return x.AsOf + } + return "" +} + type AppData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1302,180 +1310,181 @@ var file_protos_shared_vpn_proto_rawDesc = []byte{ 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x7f, 0x0a, 0x09, 0x42, 0x61, 0x6e, 0x64, 0x77, - 0x69, 0x64, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x69, 0x62, 0x55, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x07, 0x6d, 0x69, 0x62, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x69, 0x62, 0x41, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6d, 0x69, - 0x62, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x74, 0x6c, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x74, - 0x6c, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x79, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x44, - 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x63, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x12, 0x24, 0x0a, - 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x22, 0x30, 0x0a, 0x08, 0x41, 0x70, 0x70, 0x73, 0x44, 0x61, 0x74, 0x61, 0x12, - 0x24, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x08, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x61, 0x70, 0x70, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x46, 0x0a, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0x2c, 0x0a, - 0x07, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x22, 0x0a, 0x05, 0x50, - 0x6c, 0x61, 0x6e, 0x73, 0x12, 0x19, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x22, - 0xd4, 0x05, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x65, - 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x62, - 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x64, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x75, 0x73, 0x64, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x72, 0x69, 0x63, 0x65, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a, 0x14, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x50, 0x6c, 0x61, - 0x6e, 0x2e, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, - 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x65, 0x78, 0x70, + 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x09, 0x42, 0x61, 0x6e, 0x64, + 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x69, 0x62, 0x55, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x6d, 0x69, 0x62, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x69, 0x62, + 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6d, + 0x69, 0x62, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x54, 0x54, 0x4c, + 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x54, + 0x54, 0x4c, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x41, 0x73, 0x4f, + 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x41, 0x73, 0x4f, 0x66, 0x22, 0x79, 0x0a, + 0x07, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x69, 0x63, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x63, + 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x30, 0x0a, 0x08, 0x41, 0x70, 0x70, 0x73, + 0x44, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x41, 0x70, 0x70, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x08, 0x61, 0x70, 0x70, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x46, 0x0a, 0x06, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x22, 0x2c, 0x0a, 0x07, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x21, 0x0a, + 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, + 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x22, 0x22, 0x0a, 0x05, 0x50, 0x6c, 0x61, 0x6e, 0x73, 0x12, 0x19, 0x0a, 0x04, 0x70, 0x6c, 0x61, + 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x04, + 0x70, 0x6c, 0x61, 0x6e, 0x22, 0xd4, 0x05, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x1c, 0x0a, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x62, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1a, 0x0a, + 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, + 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, + 0x65, 0x12, 0x53, 0x0a, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x6e, + 0x74, 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, + 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, + 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, + 0x6f, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, + 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, + 0x0a, 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, 0x73, 0x74, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, + 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, + 0x12, 0x26, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, 0x6f, 0x6e, + 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x74, 0x65, 0x64, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6e, 0x65, + 0x77, 0x61, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, + 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x12, 0x53, 0x0a, 0x14, 0x72, 0x65, + 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, + 0x52, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x45, 0x78, 0x70, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x6e, 0x65, 0x77, + 0x61, 0x6c, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x1a, + 0x38, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x47, 0x0a, 0x19, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, - 0x65, 0x12, 0x36, 0x0a, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x42, 0x69, - 0x6c, 0x6c, 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, - 0x65, 0x64, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x6e, 0x65, - 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x6f, 0x6e, 0x65, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1c, 0x0a, - 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x64, 0x42, 0x6f, - 0x6e, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x65, - 0x78, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, - 0x6c, 0x54, 0x65, 0x78, 0x74, 0x12, 0x53, 0x0a, 0x14, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, - 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0d, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x52, 0x65, 0x6e, 0x65, 0x77, - 0x61, 0x6c, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x42, 0x6f, 0x6e, - 0x75, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x1a, 0x38, 0x0a, 0x0a, 0x50, 0x72, - 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x47, 0x0a, 0x19, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x50, 0x72, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x47, 0x0a, - 0x19, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x45, 0x78, 0x70, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xac, 0x01, 0x0a, 0x10, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x44, 0x61, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, - 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x58, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x2f, - 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, - 0xd2, 0x03, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, - 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, - 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x07, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x22, 0x0a, 0x0c, 0x79, 0x69, 0x6e, 0x62, 0x69, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x79, 0x69, 0x6e, 0x62, 0x69, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x73, 0x18, - 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x73, 0x12, - 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x08, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x09, 0x70, - 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, - 0x2e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x52, 0x09, 0x70, 0x75, 0x72, 0x63, 0x68, - 0x61, 0x73, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x08, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x70, 0x6c, 0x61, 0x6e, 0x22, 0x56, 0x0a, 0x0c, 0x42, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x22, 0xd4, 0x01, 0x0a, - 0x16, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, - 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, - 0x61, 0x6c, 0x65, 0x22, 0xd5, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x52, 0x65, - 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, - 0x65, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6d, 0x70, - 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4b, 0x65, 0x79, 0x12, - 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x7d, 0x0a, 0x17, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x1a, - 0x0a, 0x08, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x22, 0x84, 0x01, 0x0a, 0x0c, 0x4c, - 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x47, 0x0a, 0x19, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x42, 0x6f, 0x6e, + 0x75, 0x73, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xac, 0x01, 0x0a, 0x10, + 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x73, + 0x12, 0x2f, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x58, 0x0a, 0x0d, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x12, 0x2f, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x22, 0xd2, 0x03, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x16, 0x0a, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x73, 0x65, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x75, + 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, + 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x12, + 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x21, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x07, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x41, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x41, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x79, 0x69, 0x6e, 0x62, 0x69, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x79, 0x69, 0x6e, 0x62, + 0x69, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x76, 0x69, + 0x74, 0x65, 0x72, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x76, 0x69, + 0x74, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x65, 0x73, + 0x18, 0x0f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x65, 0x73, + 0x12, 0x27, 0x0a, 0x09, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x18, 0x10, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x52, 0x09, + 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x08, 0x50, 0x75, 0x72, + 0x63, 0x68, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0x56, 0x0a, 0x0c, 0x42, 0x61, 0x73, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x49, - 0x64, 0x42, 0x1b, 0x0a, 0x10, 0x69, 0x6f, 0x2e, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x2e, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5a, 0x07, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x49, + 0x64, 0x22, 0xd4, 0x01, 0x0a, 0x16, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1e, + 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x22, 0xd5, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x64, + 0x65, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x22, 0x0a, 0x0c, + 0x72, 0x65, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x26, 0x0a, 0x0e, + 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4b, 0x65, 0x79, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, + 0x79, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x22, 0x7d, 0x0a, 0x17, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x22, + 0x84, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x49, 0x64, 0x42, 0x1b, 0x0a, 0x10, 0x69, 0x6f, 0x2e, 0x6c, 0x61, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5a, 0x07, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 4ae060814..4057a4feb 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -957,7 +957,7 @@ func (m *SessionModel) BandwidthUpdate(p1 int, p2 int, p3 int, p4 int) error { Percent: int64(p1), MibUsed: int64(p2), MibAllowed: int64(p3), - TtlSeconds: int64(p4), + TTLSeconds: int64(p4), } return pathdb.Mutate(m.db, func(tx pathdb.TX) error { return pathdb.Put(tx, pathBandwidth, bandwidth, "") diff --git a/internalsdk/user_test.go b/internalsdk/user_test.go index 720344db1..1f1dfb724 100644 --- a/internalsdk/user_test.go +++ b/internalsdk/user_test.go @@ -24,6 +24,8 @@ func TestCreateUser_Success(t *testing.T) { Token: "test-token", }, }, nil) + + mockSession.On("GetUserData", int64(123)).Return(nil) mockSession.On("SetUserIdAndToken", int64(123), "test-token").Return(nil) err := createUser(context.Background(), mockProClient, mockSession) diff --git a/internalsdk/vpn_model.go b/internalsdk/vpn_model.go index ff6da8b85..0fdb7ae75 100644 --- a/internalsdk/vpn_model.go +++ b/internalsdk/vpn_model.go @@ -107,7 +107,7 @@ func (m *VPNModel) UpdateBandwidth(percent int64, mibUsed int64, mibAllowed int6 Percent: percent, MibUsed: mibUsed, MibAllowed: mibAllowed, - TtlSeconds: ttlSeconds, + TTLSeconds: ttlSeconds, } return pathdb.Put(tx, pathBandwidth, bandwidth, "") }) diff --git a/lib/core/service/websocket_subscriber.dart b/lib/core/service/websocket_subscriber.dart index f935e2233..88d3ae8cc 100644 --- a/lib/core/service/websocket_subscriber.dart +++ b/lib/core/service/websocket_subscriber.dart @@ -109,6 +109,7 @@ class WebsocketSubscriber { case _WebsocketMessageType.bandwidth: _webSocketLogger.i("Websocket message[Bandwidth]: $message"); + // final bandwidth = message as Map; sessionModel.bandwidthNotifier.value = Bandwidth.create() ..mergeFromProto3Json(message); case _WebsocketMessageType.config: diff --git a/lib/features/vpn/protos_shared/vpn.pb.dart b/lib/features/vpn/protos_shared/vpn.pb.dart index 7c7882255..99d1db900 100644 --- a/lib/features/vpn/protos_shared/vpn.pb.dart +++ b/lib/features/vpn/protos_shared/vpn.pb.dart @@ -97,7 +97,8 @@ class Bandwidth extends $pb.GeneratedMessage { $fixnum.Int64? percent, $fixnum.Int64? mibUsed, $fixnum.Int64? mibAllowed, - $fixnum.Int64? ttlSeconds, + $fixnum.Int64? tTLSeconds, + $core.String? asOf, }) { final $result = create(); if (percent != null) { @@ -109,8 +110,11 @@ class Bandwidth extends $pb.GeneratedMessage { if (mibAllowed != null) { $result.mibAllowed = mibAllowed; } - if (ttlSeconds != null) { - $result.ttlSeconds = ttlSeconds; + if (tTLSeconds != null) { + $result.tTLSeconds = tTLSeconds; + } + if (asOf != null) { + $result.asOf = asOf; } return $result; } @@ -122,7 +126,8 @@ class Bandwidth extends $pb.GeneratedMessage { ..aInt64(1, _omitFieldNames ? '' : 'percent') ..aInt64(2, _omitFieldNames ? '' : 'mibUsed', protoName: 'mibUsed') ..aInt64(3, _omitFieldNames ? '' : 'mibAllowed', protoName: 'mibAllowed') - ..aInt64(4, _omitFieldNames ? '' : 'ttlSeconds', protoName: 'ttlSeconds') + ..aInt64(4, _omitFieldNames ? '' : 'TTLSeconds', protoName: 'TTLSeconds') + ..aOS(5, _omitFieldNames ? '' : 'AsOf', protoName: 'AsOf') ..hasRequiredFields = false ; @@ -175,13 +180,22 @@ class Bandwidth extends $pb.GeneratedMessage { void clearMibAllowed() => clearField(3); @$pb.TagNumber(4) - $fixnum.Int64 get ttlSeconds => $_getI64(3); + $fixnum.Int64 get tTLSeconds => $_getI64(3); @$pb.TagNumber(4) - set ttlSeconds($fixnum.Int64 v) { $_setInt64(3, v); } + set tTLSeconds($fixnum.Int64 v) { $_setInt64(3, v); } @$pb.TagNumber(4) - $core.bool hasTtlSeconds() => $_has(3); + $core.bool hasTTLSeconds() => $_has(3); @$pb.TagNumber(4) - void clearTtlSeconds() => clearField(4); + void clearTTLSeconds() => clearField(4); + + @$pb.TagNumber(5) + $core.String get asOf => $_getSZ(4); + @$pb.TagNumber(5) + set asOf($core.String v) { $_setString(4, v); } + @$pb.TagNumber(5) + $core.bool hasAsOf() => $_has(4); + @$pb.TagNumber(5) + void clearAsOf() => clearField(5); } class AppData extends $pb.GeneratedMessage { diff --git a/lib/features/vpn/protos_shared/vpn.pbjson.dart b/lib/features/vpn/protos_shared/vpn.pbjson.dart index 80efaecfe..d13126399 100644 --- a/lib/features/vpn/protos_shared/vpn.pbjson.dart +++ b/lib/features/vpn/protos_shared/vpn.pbjson.dart @@ -35,15 +35,16 @@ const Bandwidth$json = { {'1': 'percent', '3': 1, '4': 1, '5': 3, '10': 'percent'}, {'1': 'mibUsed', '3': 2, '4': 1, '5': 3, '10': 'mibUsed'}, {'1': 'mibAllowed', '3': 3, '4': 1, '5': 3, '10': 'mibAllowed'}, - {'1': 'ttlSeconds', '3': 4, '4': 1, '5': 3, '10': 'ttlSeconds'}, + {'1': 'TTLSeconds', '3': 4, '4': 1, '5': 3, '10': 'TTLSeconds'}, + {'1': 'AsOf', '3': 5, '4': 1, '5': 9, '10': 'AsOf'}, ], }; /// Descriptor for `Bandwidth`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List bandwidthDescriptor = $convert.base64Decode( 'CglCYW5kd2lkdGgSGAoHcGVyY2VudBgBIAEoA1IHcGVyY2VudBIYCgdtaWJVc2VkGAIgASgDUg' - 'dtaWJVc2VkEh4KCm1pYkFsbG93ZWQYAyABKANSCm1pYkFsbG93ZWQSHgoKdHRsU2Vjb25kcxgE' - 'IAEoA1IKdHRsU2Vjb25kcw=='); + 'dtaWJVc2VkEh4KCm1pYkFsbG93ZWQYAyABKANSCm1pYkFsbG93ZWQSHgoKVFRMU2Vjb25kcxgE' + 'IAEoA1IKVFRMU2Vjb25kcxISCgRBc09mGAUgASgJUgRBc09m'); @$core.Deprecated('Use appDataDescriptor instead') const AppData$json = { diff --git a/protos_shared/vpn.proto b/protos_shared/vpn.proto index 592ed1e24..c11efa62d 100644 --- a/protos_shared/vpn.proto +++ b/protos_shared/vpn.proto @@ -12,7 +12,8 @@ message Bandwidth { int64 percent = 1; // [0, 100] int64 mibUsed = 2; // in MB int64 mibAllowed = 3; // in MB - int64 ttlSeconds = 4; // number of seconds left before data reset + int64 TTLSeconds = 4; // number of seconds left before data reset + string AsOf =5; } message AppData {