From 14b91368dc799d51c2dee14afd4b545abba50f72 Mon Sep 17 00:00:00 2001 From: kilimnik Date: Thu, 22 Dec 2022 21:55:25 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 1 + LICENSE.md | 21 + README.md | 31 + api/api/v1/api.proto | 51 + api/buf.gen.yaml | 24 + api/buf.yaml | 7 + app/.gitignore | 44 + app/.metadata | 33 + app/README.md | 16 + app/analysis_options.yaml | 29 + app/android/.gitignore | 13 + app/android/app/build.gradle | 79 ++ app/android/app/google-services.json | 46 + app/android/app/src/debug/AndroidManifest.xml | 8 + app/android/app/src/main/AndroidManifest.xml | 38 + .../kotlin/com/vepiot/app/MainActivity.kt | 32 + .../main/res/drawable-hdpi/ic_stat_logo.png | Bin 0 -> 1067 bytes .../main/res/drawable-mdpi/ic_stat_logo.png | Bin 0 -> 687 bytes .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable-xhdpi/ic_stat_logo.png | Bin 0 -> 1644 bytes .../main/res/drawable-xxhdpi/ic_stat_logo.png | Bin 0 -> 2379 bytes .../res/drawable-xxxhdpi/ic_stat_logo.png | Bin 0 -> 3601 bytes .../main/res/drawable/launch_background.xml | 12 + .../app/src/main/res/drawable/logo.xml | 54 + .../app/src/main/res/values/colors.xml | 17 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 8 + app/android/build.gradle | 34 + app/android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 + app/android/proguard.cfg | 27 + app/android/settings.gradle | 11 + app/ios/.gitignore | 34 + app/ios/Flutter/AppFrameworkInfo.plist | 26 + app/ios/Flutter/Debug.xcconfig | 1 + app/ios/Flutter/Release.xcconfig | 1 + app/ios/Runner.xcodeproj/project.pbxproj | 483 ++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 87 ++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + app/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + app/ios/Runner/Base.lproj/Main.storyboard | 26 + app/ios/Runner/GoogleService-Info.plist | 34 + app/ios/Runner/Info.plist | 51 + app/ios/Runner/Runner-Bridging-Header.h | 1 + app/ios/firebase_app_id_file.json | 7 + app/lib/auth.dart | 20 + app/lib/config.dart | 26 + app/lib/fcm.dart | 85 ++ app/lib/firebase_options.dart | 69 ++ app/lib/gen/api/v1/api.pb.dart | 396 +++++++ app/lib/gen/api/v1/api.pbenum.dart | 47 + app/lib/gen/api/v1/api.pbjson.dart | 118 ++ app/lib/gen/api/v1/api.pbserver.dart | 41 + app/lib/main.dart | 213 ++++ app/lib/notification.dart | 85 ++ app/lib/otp.dart | 91 ++ app/lib/otp.g.dart | 28 + app/lib/storage.dart | 60 + app/lib/unlock.dart | 101 ++ app/lib/unlocker.dart | 32 + app/pubspec.lock | 1034 +++++++++++++++++ app/pubspec.yaml | 104 ++ auth_proxy/gen/api/v1/api.pb.go | 662 +++++++++++ .../gen/api/v1/v1connect/api.connect.go | 108 ++ auth_proxy/go.mod | 14 + auth_proxy/go.sum | 14 + auth_proxy/main.go | 83 ++ flake.lock | 60 + flake.nix | 48 + logo.svg | 146 +++ vault_plugin/.gitignore | 5 + vault_plugin/Makefile | 32 + vault_plugin/README.md | 44 + vault_plugin/backend.go | 443 +++++++ vault_plugin/cmd/vepiot/main.go | 30 + vault_plugin/gen/api/v1/api.pb.go | 662 +++++++++++ .../gen/api/v1/v1connect/api.connect.go | 108 ++ vault_plugin/go.mod | 74 ++ vault_plugin/go.sum | 456 ++++++++ vault_plugin/helper.go | 22 + 107 files changed, 7232 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 api/api/v1/api.proto create mode 100644 api/buf.gen.yaml create mode 100644 api/buf.yaml create mode 100644 app/.gitignore create mode 100644 app/.metadata create mode 100644 app/README.md create mode 100644 app/analysis_options.yaml create mode 100644 app/android/.gitignore create mode 100644 app/android/app/build.gradle create mode 100644 app/android/app/google-services.json create mode 100644 app/android/app/src/debug/AndroidManifest.xml create mode 100644 app/android/app/src/main/AndroidManifest.xml create mode 100644 app/android/app/src/main/kotlin/com/vepiot/app/MainActivity.kt create mode 100644 app/android/app/src/main/res/drawable-hdpi/ic_stat_logo.png create mode 100644 app/android/app/src/main/res/drawable-mdpi/ic_stat_logo.png create mode 100644 app/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 app/android/app/src/main/res/drawable-xhdpi/ic_stat_logo.png create mode 100644 app/android/app/src/main/res/drawable-xxhdpi/ic_stat_logo.png create mode 100644 app/android/app/src/main/res/drawable-xxxhdpi/ic_stat_logo.png create mode 100644 app/android/app/src/main/res/drawable/launch_background.xml create mode 100644 app/android/app/src/main/res/drawable/logo.xml create mode 100644 app/android/app/src/main/res/values/colors.xml create mode 100644 app/android/app/src/main/res/values/styles.xml create mode 100644 app/android/app/src/profile/AndroidManifest.xml create mode 100644 app/android/build.gradle create mode 100644 app/android/gradle.properties create mode 100644 app/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 app/android/proguard.cfg create mode 100644 app/android/settings.gradle create mode 100644 app/ios/.gitignore create mode 100644 app/ios/Flutter/AppFrameworkInfo.plist create mode 100644 app/ios/Flutter/Debug.xcconfig create mode 100644 app/ios/Flutter/Release.xcconfig create mode 100644 app/ios/Runner.xcodeproj/project.pbxproj create mode 100644 app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 app/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 app/ios/Runner/AppDelegate.swift create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 app/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 app/ios/Runner/Base.lproj/Main.storyboard create mode 100644 app/ios/Runner/GoogleService-Info.plist create mode 100644 app/ios/Runner/Info.plist create mode 100644 app/ios/Runner/Runner-Bridging-Header.h create mode 100644 app/ios/firebase_app_id_file.json create mode 100644 app/lib/auth.dart create mode 100644 app/lib/config.dart create mode 100644 app/lib/fcm.dart create mode 100644 app/lib/firebase_options.dart create mode 100644 app/lib/gen/api/v1/api.pb.dart create mode 100644 app/lib/gen/api/v1/api.pbenum.dart create mode 100644 app/lib/gen/api/v1/api.pbjson.dart create mode 100644 app/lib/gen/api/v1/api.pbserver.dart create mode 100644 app/lib/main.dart create mode 100644 app/lib/notification.dart create mode 100644 app/lib/otp.dart create mode 100644 app/lib/otp.g.dart create mode 100644 app/lib/storage.dart create mode 100644 app/lib/unlock.dart create mode 100644 app/lib/unlocker.dart create mode 100644 app/pubspec.lock create mode 100644 app/pubspec.yaml create mode 100644 auth_proxy/gen/api/v1/api.pb.go create mode 100644 auth_proxy/gen/api/v1/v1connect/api.connect.go create mode 100644 auth_proxy/go.mod create mode 100644 auth_proxy/go.sum create mode 100644 auth_proxy/main.go create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 logo.svg create mode 100644 vault_plugin/.gitignore create mode 100644 vault_plugin/Makefile create mode 100644 vault_plugin/README.md create mode 100644 vault_plugin/backend.go create mode 100644 vault_plugin/cmd/vepiot/main.go create mode 100644 vault_plugin/gen/api/v1/api.pb.go create mode 100644 vault_plugin/gen/api/v1/v1connect/api.connect.go create mode 100644 vault_plugin/go.mod create mode 100644 vault_plugin/go.sum create mode 100644 vault_plugin/helper.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2744c99 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +keys/ \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..63b4b68 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..410b778 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# Vepiot + +This is a authentication plugin for [Hashicorp Vault](https://github.com/hashicorp/vault). + +The idea of this plugin is to add a manual human step into the authentication process. This works by registering the app with the vault and every time the vault tries to authenticate via this service. The service makes a push notification via firebase. The user can accept the authentication or deny it. + +```mermaid +sequenceDiagram + +loop + Vault->>+Proxy: Did someone respond to Vault_X? + Proxy-->>-Vault: No +end +Vault->>Firebase: Accept or Deny Vault_X login? +Firebase->>Mobile Devices: Accept or Deny Vault_X login? +Mobile Devices->>Proxy: Accept login to Vault_X! + +Vault->>+Proxy: Did someone respond to Vault_X? +Proxy-->>-Vault: Accept login to Vault_X! + +Vault->>Firebase: Login to Vault_X accepted. +Firebase->>Mobile Devices: Login to Vault_X accepted. + +Note right of Vault: Login Accepted +``` + +## TODO: +* CI/CD +* More secure device registration +* Testcases +* ... \ No newline at end of file diff --git a/api/api/v1/api.proto b/api/api/v1/api.proto new file mode 100644 index 0000000..0da32e4 --- /dev/null +++ b/api/api/v1/api.proto @@ -0,0 +1,51 @@ +syntax = "proto3"; + +package api.v1; + +enum TOTPResponseType { + TOTP_RESPONSE_TYPE_UNSPECIFIED = 0; + TOTP_RESPONSE_TYPE_ALLOW = 1; + TOTP_RESPONSE_TYPE_DENY = 2; +} + +message TOTPResponse { + TOTPResponseType type = 1; + string id = 2; + string totp_code = 3; + string device_id = 4; + string name = 5; +} + +message SendTOTPRequest { + TOTPResponse response = 1; +} + +message SendTOTPResponse {} + +message GetTOTPRequest { + string id = 1; +} + +message GetTOTPResponse { + TOTPResponse response = 1; +} + +service Service { + rpc SendTOTP(SendTOTPRequest) returns (SendTOTPResponse) {} + rpc GetTOTP(GetTOTPRequest) returns (GetTOTPResponse) {} +} + + +enum TOTPRequestType { + TOTP_REQUEST_TYPE_UNSPECIFIED = 0; + TOTP_REQUEST_TYPE_REQUEST = 1; + TOTP_REQUEST_TYPE_RESPONSE = 2; + TOTP_REQUEST_TYPE_CANCEL= 3; +} + +message TOTPRequest { + TOTPRequestType type = 1; + string id = 2; + string name = 3; + TOTPResponseType response_type = 4; +} diff --git a/api/buf.gen.yaml b/api/buf.gen.yaml new file mode 100644 index 0000000..f9360bf --- /dev/null +++ b/api/buf.gen.yaml @@ -0,0 +1,24 @@ +version: v1 +plugins: + - name: go + out: ../auth_proxy/gen + opt: + - paths=source_relative + - Mapi/v1/api.proto=github.com/kilimnik/vepiot/auth_proxy/gen/api/v1 + - name: connect-go + out: ../auth_proxy/gen + opt: + - paths=source_relative + - Mapi/v1/api.proto=github.com/kilimnik/vepiot/auth_proxy/gen/api/v1 + - name: go + out: ../vault_plugin/gen + opt: + - paths=source_relative + - Mapi/v1/api.proto=github.com/kilimnik/vepiot/vault_plugin/gen/api/v1 + - name: connect-go + out: ../vault_plugin/gen + opt: + - paths=source_relative + - Mapi/v1/api.proto=github.com/kilimnik/vepiot/vault_plugin/gen/api/v1 + - plugin: buf.build/protocolbuffers/dart + out: ../app/lib/gen \ No newline at end of file diff --git a/api/buf.yaml b/api/buf.yaml new file mode 100644 index 0000000..1a51945 --- /dev/null +++ b/api/buf.yaml @@ -0,0 +1,7 @@ +version: v1 +breaking: + use: + - FILE +lint: + use: + - DEFAULT diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..24476c5 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/app/.metadata b/app/.metadata new file mode 100644 index 0000000..ea04d8f --- /dev/null +++ b/app/.metadata @@ -0,0 +1,33 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + base_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + - platform: android + create_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + base_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + - platform: ios + create_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + base_revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/app/README.md b/app/README.md new file mode 100644 index 0000000..b73cfb0 --- /dev/null +++ b/app/README.md @@ -0,0 +1,16 @@ +# app + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/app/analysis_options.yaml b/app/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/app/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/app/android/.gitignore b/app/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/app/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/app/android/app/build.gradle b/app/android/app/build.gradle new file mode 100644 index 0000000..a05e61f --- /dev/null +++ b/app/android/app/build.gradle @@ -0,0 +1,79 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +// START: FlutterFire Configuration +apply plugin: 'com.google.gms.google-services' +// END: FlutterFire Configuration +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 33 + ndkVersion flutter.ndkVersion + + compileOptions { + coreLibraryDesugaringEnabled true + + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.vepiot.app" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion 21 + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + multiDexEnabled true + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.google.android.gms:play-services-base:18.1.0' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' +} diff --git a/app/android/app/google-services.json b/app/android/app/google-services.json new file mode 100644 index 0000000..0f135c7 --- /dev/null +++ b/app/android/app/google-services.json @@ -0,0 +1,46 @@ +{ + "project_info": { + "project_number": "765453437942", + "project_id": "vepiot", + "storage_bucket": "vepiot.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:765453437942:android:6388eac16f1a81648395d7", + "android_client_info": { + "package_name": "com.vepiot.app" + } + }, + "oauth_client": [ + { + "client_id": "765453437942-8o88lqsrvt1fn9ebp8v1g39hc67osh5a.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAUquRFg3O7Bw0G7uX1thLhqC0G7pcdrbQ" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "765453437942-8o88lqsrvt1fn9ebp8v1g39hc67osh5a.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "765453437942-00ima5q7tcqapq8vrj3na1a43i2l9d3u.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.vepiot.app" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/android/app/src/debug/AndroidManifest.xml b/app/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..de652cd --- /dev/null +++ b/app/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/app/android/app/src/main/AndroidManifest.xml b/app/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a8d3ae5 --- /dev/null +++ b/app/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/android/app/src/main/kotlin/com/vepiot/app/MainActivity.kt b/app/android/app/src/main/kotlin/com/vepiot/app/MainActivity.kt new file mode 100644 index 0000000..e0c76ea --- /dev/null +++ b/app/android/app/src/main/kotlin/com/vepiot/app/MainActivity.kt @@ -0,0 +1,32 @@ +package com.vepiot.app + + +import android.os.Bundle +import android.os.PersistableBundle +import com.google.android.gms.common.ConnectionResult +import com.google.android.gms.common.GoogleApiAvailability +import io.flutter.embedding.android.FlutterFragmentActivity + + +class MainActivity: FlutterFragmentActivity() { + override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { + checkGooglePlayServices() + + super.onCreate(savedInstanceState, persistentState) + } + + override fun onResume() { + checkGooglePlayServices() + + super.onResume() + } + + private fun checkGooglePlayServices() { + val api = GoogleApiAvailability.getInstance() + val status = api.isGooglePlayServicesAvailable(this) + if (status != ConnectionResult.SUCCESS) { + api.makeGooglePlayServicesAvailable(this) + } + } + +} diff --git a/app/android/app/src/main/res/drawable-hdpi/ic_stat_logo.png b/app/android/app/src/main/res/drawable-hdpi/ic_stat_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2bc1284b51c96caad4c525ea76b0ec1d56c1968a GIT binary patch literal 1067 zcmV+`1l0S9P)Px#1am@3R0s$N2z&@+hyVZs)k#D_R9HvtmuqOvVI0SI+`^h`a>*s8Fp?v3W+wAy!PtRG;&iSAJ z|D3ZEd$Fg!=l}el-|hSVJ-_F2d?{V5`MMaNlx{*^GZI&Z0)fD69PR+cKA-QYmvdW= z?P}ihz&>niquItw=roQtgG!t(iIos!dZPORq=Svvo=p~^kvMt}+Q2d#SH?mLLfg5(VU~|pQCax(nghunc37+9RHwHp!=$r$o zAQzj4xC!x9<1xwrejNPt3YtuLM21WOULwd!lZiY?eM)A~xH1GGk<{`$42A)vI2%%T z{spP1H3YF~5I72!f>H==`LBdb0c-y#0Ouj}){M>Ksg)A|pFxucQEe5yz%NjXpH@D0 z1pP**0#9U>?ZnwJLrAsN;zCHWaX=q-9pr#!)0f$r@I5IJLSu3C2l>HJOP<${xRu?ji!WK zHO~8=dLs>2!~1<|8T)XrBtYG5&(JVET1D)A7-a{vrC>LKJg7 zPz@dj^3gw>P#*?Wr~|FYAL#4Y&{e~+5k%Sf8YT=8`y;a0SD`nEzG`Hs(G{6>K(~f+ zklKNel*|`v>O!r}jZ8=hyS?;_%)32R%D4zMpi@Ra-|}5gUsnf4fVTYmlu#w|$d! zoiZ~W+7ezVfZOz;t6RWrP=f9O-gU}rpVHwP-gFDS0Cu6<;YR9qAJU$55Cs1*U|8ru zNXLX9=*&{>WYfP2?3JryL{p@{Q*Wdf?$ePF&ZeSx1gP@mWIx8bthqMq($EY3#WAZ( z7koACW!jzVkh@)1A}b$9`qIllcNfjA{#o4fa^yueR=Lw9Ut=3U7AS=r2XnRx}MjBaZ+8002ovPDHLkV1gS!_Ot*1 literal 0 HcmV?d00001 diff --git a/app/android/app/src/main/res/drawable-mdpi/ic_stat_logo.png b/app/android/app/src/main/res/drawable-mdpi/ic_stat_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..53c7fdb7d35e9354d94816de9c12443caea82fd5 GIT binary patch literal 687 zcmV;g0#N;lP)Px#1am@3R0s$N2z&@+hyVZrSxH1eR7gwZluJleQ51&nK@)m`ibC{2qL~JQf#^Ud z3TpJg1P7u84blc>>OetpB%+~$;-o=T5R{5wgc_8i2ogiENnv242qA=w61BX3zpNv> zJ8N08p z-9IDX<3x<#!x$f4+eF|v`!8U`1eUfeAVWlMF;yUtxrsm)`yEh+&3MpeJpvqQoo1oF zW}fAPmEAUhD{ug37oi2-K`Tt}R^+c5Si$meTn-Q56(oS{7U55Xhz{BQyxFaAsCByy zMYdF(#CQ(FpFH1WEm0LOD4-M`h7ZsNg%A$|d@I4|_W*%&*iG2Ug9nnJB9rqzxC<(J z6Ffp>IqF42K(%=crGfOwc?^7kbSQv(a0GPvGYEWJ6R_Ot!e}h;V!?IBd$p)KE6&;X z1sd%Doy?a&sg$pJ{B-&P3aJK^(=KS^W!QIyKoV;?xN3WPr*CKBEM&tIcmtzw8{Xoh z%on)AMv)2VRz7pv69J{-Jluz5@C9mFKeYW~<|&v4{bF9?qat|GLhi}^2s9&dN|8aC z?SEv>feaV~dXGXazIvh-*%v_|)||I9AA@S>g<(*8x?_fid;~skS-_$=&D;$s zPy#2E3Q(u{LmhNOQ6ca<(nV9JsFyzlf4wGhhgnXZ!gEl*HPj%=zq)EvcR-uL8Ys^y z+y!WWA)UfGoob=q^AAv)R)QMfmpPxre$KUb1(f5 + + + + + + + diff --git a/app/android/app/src/main/res/drawable-xhdpi/ic_stat_logo.png b/app/android/app/src/main/res/drawable-xhdpi/ic_stat_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..91eb1989801ee649b588eb1e7fa63831e4c6dd2e GIT binary patch literal 1644 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 literal 0 HcmV?d00001 diff --git a/app/android/app/src/main/res/drawable-xxxhdpi/ic_stat_logo.png b/app/android/app/src/main/res/drawable-xxxhdpi/ic_stat_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..3c804bc0082cd343666f3deb9f4df0518d02dfe1 GIT binary patch literal 3601 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 X`dtj2Ep&)&00000NkvXXu0mjfpwpl~ literal 0 HcmV?d00001 diff --git a/app/android/app/src/main/res/drawable/launch_background.xml b/app/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..b0a05a7 --- /dev/null +++ b/app/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/app/android/app/src/main/res/drawable/logo.xml b/app/android/app/src/main/res/drawable/logo.xml new file mode 100644 index 0000000..690572e --- /dev/null +++ b/app/android/app/src/main/res/drawable/logo.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/app/android/app/src/main/res/values/colors.xml b/app/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..b453065 --- /dev/null +++ b/app/android/app/src/main/res/values/colors.xml @@ -0,0 +1,17 @@ + + + #fff7e1 + #feebb4 + #fedd82 + #fecf50 + #fdc52b + #fdbb05 + #fdb504 + #fcac04 + #fca403 + #fc9601 + #ffffff + #fff8ef + #ffe0bc + #ffd5a2 + \ No newline at end of file diff --git a/app/android/app/src/main/res/values/styles.xml b/app/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/app/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/app/android/app/src/profile/AndroidManifest.xml b/app/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..de652cd --- /dev/null +++ b/app/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/app/android/build.gradle b/app/android/build.gradle new file mode 100644 index 0000000..3b267d3 --- /dev/null +++ b/app/android/build.gradle @@ -0,0 +1,34 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.2.0' + // START: FlutterFire Configuration + classpath 'com.google.gms:google-services:4.3.10' + // END: FlutterFire Configuration + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/app/android/gradle.properties b/app/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/app/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/app/android/gradle/wrapper/gradle-wrapper.properties b/app/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/app/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/app/android/proguard.cfg b/app/android/proguard.cfg new file mode 100644 index 0000000..f8768e4 --- /dev/null +++ b/app/android/proguard.cfg @@ -0,0 +1,27 @@ +## Gson rules +# Gson uses generic type information stored in a class file when working with fields. Proguard +# removes such information by default, so configure it to keep all of it. +-keepattributes Signature + +# For using GSON @Expose annotation +-keepattributes *Annotation* + +# Gson specific classes +-dontwarn sun.misc.** +#-keep class com.google.gson.stream.** { *; } + +# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory, +# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter) +-keep class * extends com.google.gson.TypeAdapter +-keep class * implements com.google.gson.TypeAdapterFactory +-keep class * implements com.google.gson.JsonSerializer +-keep class * implements com.google.gson.JsonDeserializer + +# Prevent R8 from leaving Data object members always null +-keepclassmembers,allowobfuscation class * { + @com.google.gson.annotations.SerializedName ; +} + +# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher. +-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken +-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken \ No newline at end of file diff --git a/app/android/settings.gradle b/app/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/app/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/app/ios/.gitignore b/app/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/app/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/app/ios/Flutter/AppFrameworkInfo.plist b/app/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9625e10 --- /dev/null +++ b/app/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/app/ios/Flutter/Debug.xcconfig b/app/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/app/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/app/ios/Flutter/Release.xcconfig b/app/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/app/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/app/ios/Runner.xcodeproj/project.pbxproj b/app/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..d30832c --- /dev/null +++ b/app/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,483 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.vepiot.app; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.vepiot.app; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.vepiot.app; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..c87d15a --- /dev/null +++ b/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/app/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/ios/Runner/AppDelegate.swift b/app/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/app/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/app/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/app/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/ios/Runner/Base.lproj/Main.storyboard b/app/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/app/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/ios/Runner/GoogleService-Info.plist b/app/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..2dafe36 --- /dev/null +++ b/app/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,34 @@ + + + + + CLIENT_ID + 765453437942-00ima5q7tcqapq8vrj3na1a43i2l9d3u.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.765453437942-00ima5q7tcqapq8vrj3na1a43i2l9d3u + API_KEY + AIzaSyAuitwmuA3N_i5m6I1s-VnhsflVkyzdBNU + GCM_SENDER_ID + 765453437942 + PLIST_VERSION + 1 + BUNDLE_ID + com.vepiot.app + PROJECT_ID + vepiot + STORAGE_BUCKET + vepiot.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:765453437942:ios:05d46f6d9872aeb78395d7 + + \ No newline at end of file diff --git a/app/ios/Runner/Info.plist b/app/ios/Runner/Info.plist new file mode 100644 index 0000000..3011a7d --- /dev/null +++ b/app/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + App + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + app + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/app/ios/Runner/Runner-Bridging-Header.h b/app/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/app/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/app/ios/firebase_app_id_file.json b/app/ios/firebase_app_id_file.json new file mode 100644 index 0000000..3acae20 --- /dev/null +++ b/app/ios/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:765453437942:ios:05d46f6d9872aeb78395d7", + "FIREBASE_PROJECT_ID": "vepiot", + "GCM_SENDER_ID": "765453437942" +} \ No newline at end of file diff --git a/app/lib/auth.dart b/app/lib/auth.dart new file mode 100644 index 0000000..ade637a --- /dev/null +++ b/app/lib/auth.dart @@ -0,0 +1,20 @@ +import 'package:flutter/services.dart'; +import 'package:local_auth/local_auth.dart'; + +class AuthenticationService { + static final LocalAuthentication auth = LocalAuthentication(); + + static Future authenticate() async { + try { + final bool didAuthenticate = await auth.authenticate( + localizedReason: 'Please authenticate to open app', + options: const AuthenticationOptions( + sensitiveTransaction: true, + ) + ); + return didAuthenticate; + } on PlatformException catch (e) { + return false; + } + } +} \ No newline at end of file diff --git a/app/lib/config.dart b/app/lib/config.dart new file mode 100644 index 0000000..59e84a4 --- /dev/null +++ b/app/lib/config.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_settings_screens/flutter_settings_screens.dart'; + +class ConfigScreen extends StatelessWidget { + ConfigScreen({key}) : super(key: key) { + if (!Settings.containsKey('proxy-url')!) { + Settings.setValue('proxy-url', "http://127.0.0.1:8080"); + } + } + + @override + Widget build(BuildContext context) { + return SettingsScreen( + title: "Application Settings", + children: [ + TextInputSettingsTile( + title: 'Proxy Server', + settingKey: 'proxy-url', + initialValue: 'http://127.0.0.1:8080', + borderColor: Colors.blueAccent, + errorColor: Colors.deepOrangeAccent, + ), + ], + ); + } +} \ No newline at end of file diff --git a/app/lib/fcm.dart b/app/lib/fcm.dart new file mode 100644 index 0000000..165f0e1 --- /dev/null +++ b/app/lib/fcm.dart @@ -0,0 +1,85 @@ +import 'dart:convert'; + +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:vepiot/gen/api/v1/api.pb.dart'; +import 'package:vepiot/notification.dart'; +import 'package:vepiot/storage.dart'; + +import 'firebase_options.dart'; + +class FCM extends ChangeNotifier { + @pragma('vm:entry-point') + static Future totpRequest(RemoteMessage message) async { + TOTPRequest request = TOTPRequest.create() + ..mergeFromProto3Json(jsonDecode(message.data["proto"])); + + await StorageService.readOTP(); + if (!StorageService.OTPs.value.containsKey(request.name)) { + return; + } + + var token = await StorageService.readFCMToken(); + var otp = StorageService.OTPs.value[request.name]!; + + switch (request.type) { + case TOTPRequestType.TOTP_REQUEST_TYPE_REQUEST: + otp.requestId = request.id; + break; + case TOTPRequestType.TOTP_REQUEST_TYPE_RESPONSE: + case TOTPRequestType.TOTP_REQUEST_TYPE_CANCEL: + otp.requestId = null; + break; + case TOTPRequestType.TOTP_REQUEST_TYPE_UNSPECIFIED: + break; + } + + StorageService.OTPs.notifyListeners(); + await StorageService.writeOTP(); + await NotificationService.fireNotification(request, token!); + } + + static void init(context) async { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + + await FirebaseMessaging.instance.getToken(); + + NotificationService.init(context); + + // NotificationSettings settings = await FirebaseMessaging.instance.requestPermission( + // alert: true, + // announcement: false, + // badge: true, + // carPlay: false, + // criticalAlert: false, + // provisional: false, + // sound: true, + // ); + // + // switch (settings.authorizationStatus) { + // case AuthorizationStatus.authorized: + // break; + // case AuthorizationStatus.denied: + // ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + // content: Text("Notification Permission required please activate it manually."), + // )); + // break; + // case AuthorizationStatus.notDetermined: + // break; + // case AuthorizationStatus.provisional: + // break; + // } + + FirebaseMessaging.onBackgroundMessage(totpRequest); + FirebaseMessaging.onMessage.listen(totpRequest); + } + + static Future getToken() async { + var token = await FirebaseMessaging.instance.getToken(); + await StorageService.writeFCMToken(token); + return token; + } +} diff --git a/app/lib/firebase_options.dart b/app/lib/firebase_options.dart new file mode 100644 index 0000000..256ea2f --- /dev/null +++ b/app/lib/firebase_options.dart @@ -0,0 +1,69 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for web - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyAUquRFg3O7Bw0G7uX1thLhqC0G7pcdrbQ', + appId: '1:765453437942:android:6388eac16f1a81648395d7', + messagingSenderId: '765453437942', + projectId: 'vepiot', + storageBucket: 'vepiot.appspot.com', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyAuitwmuA3N_i5m6I1s-VnhsflVkyzdBNU', + appId: '1:765453437942:ios:05d46f6d9872aeb78395d7', + messagingSenderId: '765453437942', + projectId: 'vepiot', + storageBucket: 'vepiot.appspot.com', + iosClientId: '765453437942-00ima5q7tcqapq8vrj3na1a43i2l9d3u.apps.googleusercontent.com', + iosBundleId: 'com.vepiot.app', + ); +} diff --git a/app/lib/gen/api/v1/api.pb.dart b/app/lib/gen/api/v1/api.pb.dart new file mode 100644 index 0000000..1aed5e8 --- /dev/null +++ b/app/lib/gen/api/v1/api.pb.dart @@ -0,0 +1,396 @@ +/// +// Generated code. Do not modify. +// source: api/v1/api.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name + +import 'dart:async' as $async; +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'api.pbenum.dart'; + +export 'api.pbenum.dart'; + +class TOTPResponse extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TOTPResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'api.v1'), createEmptyInstance: create) + ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'type', $pb.PbFieldType.OE, defaultOrMaker: TOTPResponseType.TOTP_RESPONSE_TYPE_UNSPECIFIED, valueOf: TOTPResponseType.valueOf, enumValues: TOTPResponseType.values) + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'totpCode') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'deviceId') + ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..hasRequiredFields = false + ; + + TOTPResponse._() : super(); + factory TOTPResponse({ + TOTPResponseType? type, + $core.String? id, + $core.String? totpCode, + $core.String? deviceId, + $core.String? name, + }) { + final _result = create(); + if (type != null) { + _result.type = type; + } + if (id != null) { + _result.id = id; + } + if (totpCode != null) { + _result.totpCode = totpCode; + } + if (deviceId != null) { + _result.deviceId = deviceId; + } + if (name != null) { + _result.name = name; + } + return _result; + } + factory TOTPResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory TOTPResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + TOTPResponse clone() => TOTPResponse()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + TOTPResponse copyWith(void Function(TOTPResponse) updates) => super.copyWith((message) => updates(message as TOTPResponse)) as TOTPResponse; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static TOTPResponse create() => TOTPResponse._(); + TOTPResponse createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static TOTPResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TOTPResponse? _defaultInstance; + + @$pb.TagNumber(1) + TOTPResponseType get type => $_getN(0); + @$pb.TagNumber(1) + set type(TOTPResponseType v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasType() => $_has(0); + @$pb.TagNumber(1) + void clearType() => clearField(1); + + @$pb.TagNumber(2) + $core.String get id => $_getSZ(1); + @$pb.TagNumber(2) + set id($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasId() => $_has(1); + @$pb.TagNumber(2) + void clearId() => clearField(2); + + @$pb.TagNumber(3) + $core.String get totpCode => $_getSZ(2); + @$pb.TagNumber(3) + set totpCode($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasTotpCode() => $_has(2); + @$pb.TagNumber(3) + void clearTotpCode() => clearField(3); + + @$pb.TagNumber(4) + $core.String get deviceId => $_getSZ(3); + @$pb.TagNumber(4) + set deviceId($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasDeviceId() => $_has(3); + @$pb.TagNumber(4) + void clearDeviceId() => clearField(4); + + @$pb.TagNumber(5) + $core.String get name => $_getSZ(4); + @$pb.TagNumber(5) + set name($core.String v) { $_setString(4, v); } + @$pb.TagNumber(5) + $core.bool hasName() => $_has(4); + @$pb.TagNumber(5) + void clearName() => clearField(5); +} + +class SendTOTPRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SendTOTPRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'api.v1'), createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'response', subBuilder: TOTPResponse.create) + ..hasRequiredFields = false + ; + + SendTOTPRequest._() : super(); + factory SendTOTPRequest({ + TOTPResponse? response, + }) { + final _result = create(); + if (response != null) { + _result.response = response; + } + return _result; + } + factory SendTOTPRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SendTOTPRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + SendTOTPRequest clone() => SendTOTPRequest()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SendTOTPRequest copyWith(void Function(SendTOTPRequest) updates) => super.copyWith((message) => updates(message as SendTOTPRequest)) as SendTOTPRequest; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SendTOTPRequest create() => SendTOTPRequest._(); + SendTOTPRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SendTOTPRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SendTOTPRequest? _defaultInstance; + + @$pb.TagNumber(1) + TOTPResponse get response => $_getN(0); + @$pb.TagNumber(1) + set response(TOTPResponse v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasResponse() => $_has(0); + @$pb.TagNumber(1) + void clearResponse() => clearField(1); + @$pb.TagNumber(1) + TOTPResponse ensureResponse() => $_ensure(0); +} + +class SendTOTPResponse extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SendTOTPResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'api.v1'), createEmptyInstance: create) + ..hasRequiredFields = false + ; + + SendTOTPResponse._() : super(); + factory SendTOTPResponse() => create(); + factory SendTOTPResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SendTOTPResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + SendTOTPResponse clone() => SendTOTPResponse()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + SendTOTPResponse copyWith(void Function(SendTOTPResponse) updates) => super.copyWith((message) => updates(message as SendTOTPResponse)) as SendTOTPResponse; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SendTOTPResponse create() => SendTOTPResponse._(); + SendTOTPResponse createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static SendTOTPResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static SendTOTPResponse? _defaultInstance; +} + +class GetTOTPRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetTOTPRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'api.v1'), createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') + ..hasRequiredFields = false + ; + + GetTOTPRequest._() : super(); + factory GetTOTPRequest({ + $core.String? id, + }) { + final _result = create(); + if (id != null) { + _result.id = id; + } + return _result; + } + factory GetTOTPRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GetTOTPRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + GetTOTPRequest clone() => GetTOTPRequest()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + GetTOTPRequest copyWith(void Function(GetTOTPRequest) updates) => super.copyWith((message) => updates(message as GetTOTPRequest)) as GetTOTPRequest; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GetTOTPRequest create() => GetTOTPRequest._(); + GetTOTPRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static GetTOTPRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static GetTOTPRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get id => $_getSZ(0); + @$pb.TagNumber(1) + set id($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => clearField(1); +} + +class GetTOTPResponse extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GetTOTPResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'api.v1'), createEmptyInstance: create) + ..aOM(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'response', subBuilder: TOTPResponse.create) + ..hasRequiredFields = false + ; + + GetTOTPResponse._() : super(); + factory GetTOTPResponse({ + TOTPResponse? response, + }) { + final _result = create(); + if (response != null) { + _result.response = response; + } + return _result; + } + factory GetTOTPResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GetTOTPResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + GetTOTPResponse clone() => GetTOTPResponse()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + GetTOTPResponse copyWith(void Function(GetTOTPResponse) updates) => super.copyWith((message) => updates(message as GetTOTPResponse)) as GetTOTPResponse; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GetTOTPResponse create() => GetTOTPResponse._(); + GetTOTPResponse createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static GetTOTPResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static GetTOTPResponse? _defaultInstance; + + @$pb.TagNumber(1) + TOTPResponse get response => $_getN(0); + @$pb.TagNumber(1) + set response(TOTPResponse v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasResponse() => $_has(0); + @$pb.TagNumber(1) + void clearResponse() => clearField(1); + @$pb.TagNumber(1) + TOTPResponse ensureResponse() => $_ensure(0); +} + +class TOTPRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TOTPRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'api.v1'), createEmptyInstance: create) + ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'type', $pb.PbFieldType.OE, defaultOrMaker: TOTPRequestType.TOTP_REQUEST_TYPE_UNSPECIFIED, valueOf: TOTPRequestType.valueOf, enumValues: TOTPRequestType.values) + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..e(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'responseType', $pb.PbFieldType.OE, defaultOrMaker: TOTPResponseType.TOTP_RESPONSE_TYPE_UNSPECIFIED, valueOf: TOTPResponseType.valueOf, enumValues: TOTPResponseType.values) + ..hasRequiredFields = false + ; + + TOTPRequest._() : super(); + factory TOTPRequest({ + TOTPRequestType? type, + $core.String? id, + $core.String? name, + TOTPResponseType? responseType, + }) { + final _result = create(); + if (type != null) { + _result.type = type; + } + if (id != null) { + _result.id = id; + } + if (name != null) { + _result.name = name; + } + if (responseType != null) { + _result.responseType = responseType; + } + return _result; + } + factory TOTPRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory TOTPRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + TOTPRequest clone() => TOTPRequest()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + TOTPRequest copyWith(void Function(TOTPRequest) updates) => super.copyWith((message) => updates(message as TOTPRequest)) as TOTPRequest; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static TOTPRequest create() => TOTPRequest._(); + TOTPRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static TOTPRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TOTPRequest? _defaultInstance; + + @$pb.TagNumber(1) + TOTPRequestType get type => $_getN(0); + @$pb.TagNumber(1) + set type(TOTPRequestType v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasType() => $_has(0); + @$pb.TagNumber(1) + void clearType() => clearField(1); + + @$pb.TagNumber(2) + $core.String get id => $_getSZ(1); + @$pb.TagNumber(2) + set id($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasId() => $_has(1); + @$pb.TagNumber(2) + void clearId() => clearField(2); + + @$pb.TagNumber(3) + $core.String get name => $_getSZ(2); + @$pb.TagNumber(3) + set name($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasName() => $_has(2); + @$pb.TagNumber(3) + void clearName() => clearField(3); + + @$pb.TagNumber(4) + TOTPResponseType get responseType => $_getN(3); + @$pb.TagNumber(4) + set responseType(TOTPResponseType v) { setField(4, v); } + @$pb.TagNumber(4) + $core.bool hasResponseType() => $_has(3); + @$pb.TagNumber(4) + void clearResponseType() => clearField(4); +} + +class ServiceApi { + $pb.RpcClient _client; + ServiceApi(this._client); + + $async.Future sendTOTP($pb.ClientContext? ctx, SendTOTPRequest request) { + var emptyResponse = SendTOTPResponse(); + return _client.invoke(ctx, 'Service', 'SendTOTP', request, emptyResponse); + } + $async.Future getTOTP($pb.ClientContext? ctx, GetTOTPRequest request) { + var emptyResponse = GetTOTPResponse(); + return _client.invoke(ctx, 'Service', 'GetTOTP', request, emptyResponse); + } +} + diff --git a/app/lib/gen/api/v1/api.pbenum.dart b/app/lib/gen/api/v1/api.pbenum.dart new file mode 100644 index 0000000..f2ea9b7 --- /dev/null +++ b/app/lib/gen/api/v1/api.pbenum.dart @@ -0,0 +1,47 @@ +/// +// Generated code. Do not modify. +// source: api/v1/api.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name + +// ignore_for_file: UNDEFINED_SHOWN_NAME +import 'dart:core' as $core; +import 'package:protobuf/protobuf.dart' as $pb; + +class TOTPResponseType extends $pb.ProtobufEnum { + static const TOTPResponseType TOTP_RESPONSE_TYPE_UNSPECIFIED = TOTPResponseType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TOTP_RESPONSE_TYPE_UNSPECIFIED'); + static const TOTPResponseType TOTP_RESPONSE_TYPE_ALLOW = TOTPResponseType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TOTP_RESPONSE_TYPE_ALLOW'); + static const TOTPResponseType TOTP_RESPONSE_TYPE_DENY = TOTPResponseType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TOTP_RESPONSE_TYPE_DENY'); + + static const $core.List values = [ + TOTP_RESPONSE_TYPE_UNSPECIFIED, + TOTP_RESPONSE_TYPE_ALLOW, + TOTP_RESPONSE_TYPE_DENY, + ]; + + static final $core.Map<$core.int, TOTPResponseType> _byValue = $pb.ProtobufEnum.initByValue(values); + static TOTPResponseType? valueOf($core.int value) => _byValue[value]; + + const TOTPResponseType._($core.int v, $core.String n) : super(v, n); +} + +class TOTPRequestType extends $pb.ProtobufEnum { + static const TOTPRequestType TOTP_REQUEST_TYPE_UNSPECIFIED = TOTPRequestType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TOTP_REQUEST_TYPE_UNSPECIFIED'); + static const TOTPRequestType TOTP_REQUEST_TYPE_REQUEST = TOTPRequestType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TOTP_REQUEST_TYPE_REQUEST'); + static const TOTPRequestType TOTP_REQUEST_TYPE_RESPONSE = TOTPRequestType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TOTP_REQUEST_TYPE_RESPONSE'); + static const TOTPRequestType TOTP_REQUEST_TYPE_CANCEL = TOTPRequestType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'TOTP_REQUEST_TYPE_CANCEL'); + + static const $core.List values = [ + TOTP_REQUEST_TYPE_UNSPECIFIED, + TOTP_REQUEST_TYPE_REQUEST, + TOTP_REQUEST_TYPE_RESPONSE, + TOTP_REQUEST_TYPE_CANCEL, + ]; + + static final $core.Map<$core.int, TOTPRequestType> _byValue = $pb.ProtobufEnum.initByValue(values); + static TOTPRequestType? valueOf($core.int value) => _byValue[value]; + + const TOTPRequestType._($core.int v, $core.String n) : super(v, n); +} + diff --git a/app/lib/gen/api/v1/api.pbjson.dart b/app/lib/gen/api/v1/api.pbjson.dart new file mode 100644 index 0000000..2cc09f3 --- /dev/null +++ b/app/lib/gen/api/v1/api.pbjson.dart @@ -0,0 +1,118 @@ +/// +// Generated code. Do not modify. +// source: api/v1/api.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use tOTPResponseTypeDescriptor instead') +const TOTPResponseType$json = const { + '1': 'TOTPResponseType', + '2': const [ + const {'1': 'TOTP_RESPONSE_TYPE_UNSPECIFIED', '2': 0}, + const {'1': 'TOTP_RESPONSE_TYPE_ALLOW', '2': 1}, + const {'1': 'TOTP_RESPONSE_TYPE_DENY', '2': 2}, + ], +}; + +/// Descriptor for `TOTPResponseType`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List tOTPResponseTypeDescriptor = $convert.base64Decode('ChBUT1RQUmVzcG9uc2VUeXBlEiIKHlRPVFBfUkVTUE9OU0VfVFlQRV9VTlNQRUNJRklFRBAAEhwKGFRPVFBfUkVTUE9OU0VfVFlQRV9BTExPVxABEhsKF1RPVFBfUkVTUE9OU0VfVFlQRV9ERU5ZEAI='); +@$core.Deprecated('Use tOTPRequestTypeDescriptor instead') +const TOTPRequestType$json = const { + '1': 'TOTPRequestType', + '2': const [ + const {'1': 'TOTP_REQUEST_TYPE_UNSPECIFIED', '2': 0}, + const {'1': 'TOTP_REQUEST_TYPE_REQUEST', '2': 1}, + const {'1': 'TOTP_REQUEST_TYPE_RESPONSE', '2': 2}, + const {'1': 'TOTP_REQUEST_TYPE_CANCEL', '2': 3}, + ], +}; + +/// Descriptor for `TOTPRequestType`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List tOTPRequestTypeDescriptor = $convert.base64Decode('Cg9UT1RQUmVxdWVzdFR5cGUSIQodVE9UUF9SRVFVRVNUX1RZUEVfVU5TUEVDSUZJRUQQABIdChlUT1RQX1JFUVVFU1RfVFlQRV9SRVFVRVNUEAESHgoaVE9UUF9SRVFVRVNUX1RZUEVfUkVTUE9OU0UQAhIcChhUT1RQX1JFUVVFU1RfVFlQRV9DQU5DRUwQAw=='); +@$core.Deprecated('Use tOTPResponseDescriptor instead') +const TOTPResponse$json = const { + '1': 'TOTPResponse', + '2': const [ + const {'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.api.v1.TOTPResponseType', '10': 'type'}, + const {'1': 'id', '3': 2, '4': 1, '5': 9, '10': 'id'}, + const {'1': 'totp_code', '3': 3, '4': 1, '5': 9, '10': 'totpCode'}, + const {'1': 'device_id', '3': 4, '4': 1, '5': 9, '10': 'deviceId'}, + const {'1': 'name', '3': 5, '4': 1, '5': 9, '10': 'name'}, + ], +}; + +/// Descriptor for `TOTPResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List tOTPResponseDescriptor = $convert.base64Decode('CgxUT1RQUmVzcG9uc2USLAoEdHlwZRgBIAEoDjIYLmFwaS52MS5UT1RQUmVzcG9uc2VUeXBlUgR0eXBlEg4KAmlkGAIgASgJUgJpZBIbCgl0b3RwX2NvZGUYAyABKAlSCHRvdHBDb2RlEhsKCWRldmljZV9pZBgEIAEoCVIIZGV2aWNlSWQSEgoEbmFtZRgFIAEoCVIEbmFtZQ=='); +@$core.Deprecated('Use sendTOTPRequestDescriptor instead') +const SendTOTPRequest$json = const { + '1': 'SendTOTPRequest', + '2': const [ + const {'1': 'response', '3': 1, '4': 1, '5': 11, '6': '.api.v1.TOTPResponse', '10': 'response'}, + ], +}; + +/// Descriptor for `SendTOTPRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List sendTOTPRequestDescriptor = $convert.base64Decode('Cg9TZW5kVE9UUFJlcXVlc3QSMAoIcmVzcG9uc2UYASABKAsyFC5hcGkudjEuVE9UUFJlc3BvbnNlUghyZXNwb25zZQ=='); +@$core.Deprecated('Use sendTOTPResponseDescriptor instead') +const SendTOTPResponse$json = const { + '1': 'SendTOTPResponse', +}; + +/// Descriptor for `SendTOTPResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List sendTOTPResponseDescriptor = $convert.base64Decode('ChBTZW5kVE9UUFJlc3BvbnNl'); +@$core.Deprecated('Use getTOTPRequestDescriptor instead') +const GetTOTPRequest$json = const { + '1': 'GetTOTPRequest', + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + ], +}; + +/// Descriptor for `GetTOTPRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List getTOTPRequestDescriptor = $convert.base64Decode('Cg5HZXRUT1RQUmVxdWVzdBIOCgJpZBgBIAEoCVICaWQ='); +@$core.Deprecated('Use getTOTPResponseDescriptor instead') +const GetTOTPResponse$json = const { + '1': 'GetTOTPResponse', + '2': const [ + const {'1': 'response', '3': 1, '4': 1, '5': 11, '6': '.api.v1.TOTPResponse', '10': 'response'}, + ], +}; + +/// Descriptor for `GetTOTPResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List getTOTPResponseDescriptor = $convert.base64Decode('Cg9HZXRUT1RQUmVzcG9uc2USMAoIcmVzcG9uc2UYASABKAsyFC5hcGkudjEuVE9UUFJlc3BvbnNlUghyZXNwb25zZQ=='); +@$core.Deprecated('Use tOTPRequestDescriptor instead') +const TOTPRequest$json = const { + '1': 'TOTPRequest', + '2': const [ + const {'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.api.v1.TOTPRequestType', '10': 'type'}, + const {'1': 'id', '3': 2, '4': 1, '5': 9, '10': 'id'}, + const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'}, + const {'1': 'response_type', '3': 4, '4': 1, '5': 14, '6': '.api.v1.TOTPResponseType', '10': 'responseType'}, + ], +}; + +/// Descriptor for `TOTPRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List tOTPRequestDescriptor = $convert.base64Decode('CgtUT1RQUmVxdWVzdBIrCgR0eXBlGAEgASgOMhcuYXBpLnYxLlRPVFBSZXF1ZXN0VHlwZVIEdHlwZRIOCgJpZBgCIAEoCVICaWQSEgoEbmFtZRgDIAEoCVIEbmFtZRI9Cg1yZXNwb25zZV90eXBlGAQgASgOMhguYXBpLnYxLlRPVFBSZXNwb25zZVR5cGVSDHJlc3BvbnNlVHlwZQ=='); +const $core.Map<$core.String, $core.dynamic> ServiceBase$json = const { + '1': 'Service', + '2': const [ + const {'1': 'SendTOTP', '2': '.api.v1.SendTOTPRequest', '3': '.api.v1.SendTOTPResponse', '4': const {}}, + const {'1': 'GetTOTP', '2': '.api.v1.GetTOTPRequest', '3': '.api.v1.GetTOTPResponse', '4': const {}}, + ], +}; + +@$core.Deprecated('Use serviceDescriptor instead') +const $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> ServiceBase$messageJson = const { + '.api.v1.SendTOTPRequest': SendTOTPRequest$json, + '.api.v1.TOTPResponse': TOTPResponse$json, + '.api.v1.SendTOTPResponse': SendTOTPResponse$json, + '.api.v1.GetTOTPRequest': GetTOTPRequest$json, + '.api.v1.GetTOTPResponse': GetTOTPResponse$json, +}; + +/// Descriptor for `Service`. Decode as a `google.protobuf.ServiceDescriptorProto`. +final $typed_data.Uint8List serviceDescriptor = $convert.base64Decode('CgdTZXJ2aWNlEj8KCFNlbmRUT1RQEhcuYXBpLnYxLlNlbmRUT1RQUmVxdWVzdBoYLmFwaS52MS5TZW5kVE9UUFJlc3BvbnNlIgASPAoHR2V0VE9UUBIWLmFwaS52MS5HZXRUT1RQUmVxdWVzdBoXLmFwaS52MS5HZXRUT1RQUmVzcG9uc2UiAA=='); diff --git a/app/lib/gen/api/v1/api.pbserver.dart b/app/lib/gen/api/v1/api.pbserver.dart new file mode 100644 index 0000000..e62b800 --- /dev/null +++ b/app/lib/gen/api/v1/api.pbserver.dart @@ -0,0 +1,41 @@ +/// +// Generated code. Do not modify. +// source: api/v1/api.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name + +import 'dart:async' as $async; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'dart:core' as $core; +import 'api.pb.dart' as $0; +import 'api.pbjson.dart'; + +export 'api.pb.dart'; + +abstract class ServiceBase extends $pb.GeneratedService { + $async.Future<$0.SendTOTPResponse> sendTOTP($pb.ServerContext ctx, $0.SendTOTPRequest request); + $async.Future<$0.GetTOTPResponse> getTOTP($pb.ServerContext ctx, $0.GetTOTPRequest request); + + $pb.GeneratedMessage createRequest($core.String method) { + switch (method) { + case 'SendTOTP': return $0.SendTOTPRequest(); + case 'GetTOTP': return $0.GetTOTPRequest(); + default: throw $core.ArgumentError('Unknown method: $method'); + } + } + + $async.Future<$pb.GeneratedMessage> handleCall($pb.ServerContext ctx, $core.String method, $pb.GeneratedMessage request) { + switch (method) { + case 'SendTOTP': return this.sendTOTP(ctx, request as $0.SendTOTPRequest); + case 'GetTOTP': return this.getTOTP(ctx, request as $0.GetTOTPRequest); + default: throw $core.ArgumentError('Unknown method: $method'); + } + } + + $core.Map<$core.String, $core.dynamic> get $json => ServiceBase$json; + $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> get $messageJson => ServiceBase$messageJson; +} + diff --git a/app/lib/main.dart b/app/lib/main.dart new file mode 100644 index 0000000..ecb6e61 --- /dev/null +++ b/app/lib/main.dart @@ -0,0 +1,213 @@ +import 'dart:async'; +import 'package:flutter/services.dart'; +import 'package:vepiot/storage.dart'; +import 'package:vepiot/unlock.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_settings_screens/flutter_settings_screens.dart'; +import 'package:barcode_scan2/barcode_scan2.dart'; +import 'auth.dart'; +import 'config.dart'; +import 'fcm.dart'; +import 'otp.dart'; +import 'package:share_plus/share_plus.dart'; +import 'dart:io'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + + await Settings.init(); + await StorageService.init(); + var authenticated = await authenticate(); + + if (authenticated) { + runApp(const VepiotApp()); + } +} + +Future authenticate() async { + bool authenticated = await AuthenticationService.authenticate(); + + if (!authenticated) { + if (Platform.isIOS) { + exit(0); + } else { + SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + } + } + + return authenticated; +} + +class VepiotApp extends StatelessWidget { + const VepiotApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Vepiot', + theme: ThemeData( + colorScheme: ColorScheme.fromSwatch(primarySwatch: const MaterialColor(0xFFFDBB05, { + 50: Color(0xFFFFF7E1), + 100: Color(0xFFFEEBB4), + 200: Color(0xFFFEDD82), + 300: Color(0xFFFECF50), + 400: Color(0xFFFDC52B), + 500: Color(0xFFFDBB05), + 600: Color(0xFFFDB504), + 700: Color(0xFFFCAC04), + 800: Color(0xFFFCA403), + 900: Color(0xFFFC9601), + })).copyWith(secondary: const MaterialColor(0xFFFFF8EF, { + 100: Color(0xFFFFFFFF), + 200: Color(0xFFFFF8EF), + 400: Color(0xFFFFE0BC), + 700: Color(0xFFFFD5A2), + })), + ), + home: const MyHomePage(title: 'Vepiot'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State with WidgetsBindingObserver { + @override + void initState() { + WidgetsBinding.instance.addObserver(this); + + FCM.init(context); + + super.initState(); + + // Timer.periodic(const Duration(seconds: 1), (timer) async { + // await StorageService.readOTP(); + // setState(() { + // + // }); + // }); + } + + @override + Future didChangeAppLifecycleState(AppLifecycleState state) async { + if (state == AppLifecycleState.resumed) { + await StorageService.readOTP(); + await authenticate(); + } + } + + Future scan() async { + ScanResult result = await BarcodeScanner.scan(); + String uri = result.rawContent; + + var errorMessage = ""; + + try { + OTP otp = OTP.createOTP(uri); + setState(() => StorageService.OTPs.value[otp.username] = otp); + await StorageService.writeOTP(); + } on FormatException catch (e) { + errorMessage = e.message; + } + + if (errorMessage.isNotEmpty) { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + } + + Future handleClick(String value) async { + switch (value) { + case 'Settings': + Navigator.push( + context, + MaterialPageRoute(builder: (context) => ConfigScreen()), + ); + break; + case 'Firebase Device Id': + String? token = await FCM.getToken(); + if (token != null) { + Share.share(token); + } else { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text("No Firebase Token found"), + )); + } + break; + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("Vepiot"), + actions: [ + PopupMenuButton( + onSelected: handleClick, + itemBuilder: (BuildContext context) { + return {'Settings', 'Firebase Device Id'}.map((String choice) { + return PopupMenuItem( + value: choice, + child: Text(choice), + ); + }).toList(); + }, + ), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: scan, + tooltip: 'Add TOTP', + child: const Icon(Icons.add), + ), + body: ValueListenableBuilder( + valueListenable: StorageService.OTPs, + builder: (context, Map value, child) => ListView.builder( + itemCount: value.length, + itemBuilder: (context, index) { + OTP otp = value.values.elementAt(index); + return Dismissible( + key: Key(otp.username), + onDismissed: (direction) async { + setState(() { + value.remove(otp.username); + }); + await StorageService.writeOTP(); + }, + child: Card( + child: ListTile( + title: Text(otp.username), + trailing: otp.requestId != null + ? const Icon(Icons.notifications_active) + : const Icon(null), + onTap: () { + if (otp.requestId != null) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => UnlockScreen( + id: otp.requestId!, + name: otp.issuer, + otp: otp)), + ); + } + }, + ), + ), + ); + }), + ), + ); + } +} diff --git a/app/lib/notification.dart b/app/lib/notification.dart new file mode 100644 index 0000000..300fe44 --- /dev/null +++ b/app/lib/notification.dart @@ -0,0 +1,85 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:vepiot/storage.dart'; +import 'package:vepiot/unlocker.dart'; + +import 'gen/api/v1/api.pb.dart'; +import 'dart:developer' as developer; + +class NotificationService { + static FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + static Future init(context) async { + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('ic_stat_logo'); + const InitializationSettings initializationSettings = + InitializationSettings(android: initializationSettingsAndroid); + await flutterLocalNotificationsPlugin.initialize( + initializationSettings, + ); + + bool? granted = await flutterLocalNotificationsPlugin + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.requestPermission(); + + if (granted != null && !granted) { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text( + "Notification Permission required please activate it manually."), + )); + } + } + + static Future fireNotification( + TOTPRequest request, String deviceId) async { + switch (request.type) { + case TOTPRequestType.TOTP_REQUEST_TYPE_REQUEST: + AndroidNotificationDetails androidNotificationDetails = + AndroidNotificationDetails( + request.id, + 'unlock_request', + channelDescription: 'Unlock Request for Vault', + importance: Importance.max, + priority: Priority.high, + ); + NotificationDetails notificationDetails = + NotificationDetails(android: androidNotificationDetails); + + await flutterLocalNotificationsPlugin.show( + request.id.hashCode, + 'Vepiot Verify Unlock', + 'Someone wants to unlock Vault Auth ${request.name}', + notificationDetails); + break; + case TOTPRequestType.TOTP_REQUEST_TYPE_RESPONSE: + AndroidNotificationDetails androidNotificationDetails = + AndroidNotificationDetails(request.id, 'unlocked', + channelDescription: 'Unlocked Vault', + importance: Importance.max, + priority: Priority.high); + NotificationDetails notificationDetails = + NotificationDetails(android: androidNotificationDetails); + + await flutterLocalNotificationsPlugin.show( + 0, + 'Vepiot Verify Unlocked', + 'Someone unlocked Vault Auth ${request.name}', + notificationDetails); + await cancelNotification(request.id.hashCode); + break; + case TOTPRequestType.TOTP_REQUEST_TYPE_CANCEL: + await cancelNotification(request.id.hashCode); + break; + case TOTPRequestType.TOTP_REQUEST_TYPE_UNSPECIFIED: + break; + } + } + + static Future cancelNotification(int id) async { + await flutterLocalNotificationsPlugin.cancel(id); + } +} diff --git a/app/lib/otp.dart b/app/lib/otp.dart new file mode 100644 index 0000000..138d5cd --- /dev/null +++ b/app/lib/otp.dart @@ -0,0 +1,91 @@ +import 'package:json_annotation/json_annotation.dart'; + +import 'package:otp/otp.dart' as otp_generator; +import 'package:otp/otp.dart'; + +part 'otp.g.dart'; + +// ignore: camel_case_types +enum OTP_Type { + none, + totp, + hotp, +} + +@JsonSerializable() +class OTP { + String secret; + OTP_Type type; + String username; + String issuer; + String? requestId; + + /// A necessary factory constructor for creating a new User instance + /// from a map. Pass the map to the generated `_$UserFromJson()` constructor. + /// The constructor is named after the source class, in this case, User. + factory OTP.fromJson(Map json) => _$OTPFromJson(json); + + /// `toJson` is the convention for a class to declare support for serialization + /// to JSON. The implementation simply calls the private, generated + /// helper method `_$UserToJson`. + Map toJson() => _$OTPToJson(this); + + OTP(this.secret, this.type, this.username, this.issuer); + + String generateCode() { + switch (type) { + case OTP_Type.none: + return ""; + case OTP_Type.totp: + var currentTime = DateTime.now().toLocal().millisecondsSinceEpoch; + return otp_generator.OTP.generateTOTPCodeString(secret, currentTime, + isGoogle: true, algorithm: Algorithm.SHA1); + case OTP_Type.hotp: + return ""; + } + } + + static OTP createOTP(String stringUri) { + var uri = Uri.parse(stringUri); + + if (!uri.isScheme("otpauth")) { + throw FormatException("Wrong scheme ${uri.scheme}"); + } + + var type = OTP_Type.none; + switch (uri.authority) { + case "totp": + type = OTP_Type.totp; + break; + case "hotp": + type = OTP_Type.hotp; + throw const FormatException("HOTP not supported"); + default: + throw FormatException("Wrong OTP Type ${uri.authority}"); + } + + var params = uri.queryParameters; + + if (!params.containsKey("secret")) { + throw const FormatException("No secret provided"); + } + var secret = params["secret"]!; + + if (!params.containsKey("issuer")) { + throw const FormatException("No issuer provided"); + } + var issuer = params["issuer"]!; + + var splits = uri.pathSegments[0].split(":"); + if (splits.length != 2) { + throw const FormatException("OTP Format Wrong"); + } + + var username = splits[1]; + if (splits[0] != issuer) { + throw const FormatException("Issuer not matching"); + } + + return OTP(secret, type, username, issuer); + } +} diff --git a/app/lib/otp.g.dart b/app/lib/otp.g.dart new file mode 100644 index 0000000..d98ed59 --- /dev/null +++ b/app/lib/otp.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'otp.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +OTP _$OTPFromJson(Map json) => OTP( + json['secret'] as String, + $enumDecode(_$OTP_TypeEnumMap, json['type']), + json['username'] as String, + json['issuer'] as String, + )..requestId = json['requestId'] as String?; + +Map _$OTPToJson(OTP instance) => { + 'secret': instance.secret, + 'type': _$OTP_TypeEnumMap[instance.type]!, + 'username': instance.username, + 'issuer': instance.issuer, + 'requestId': instance.requestId, + }; + +const _$OTP_TypeEnumMap = { + OTP_Type.none: 'none', + OTP_Type.totp: 'totp', + OTP_Type.hotp: 'hotp', +}; diff --git a/app/lib/storage.dart b/app/lib/storage.dart new file mode 100644 index 0000000..b18a167 --- /dev/null +++ b/app/lib/storage.dart @@ -0,0 +1,60 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'dart:async'; +import 'otp.dart'; + +class StorageService { + static const _secureStorage = FlutterSecureStorage(); + static const otpKey = "OTP"; + static const fcmKey = "fcm"; + + static ValueNotifier> OTPs = ValueNotifier>({}); + + static Future init() async { + await readOTP(); + } + + static AndroidOptions _getAndroidOptions() => const AndroidOptions( + encryptedSharedPreferences: true, + ); + + static Future writeOTP() async { + var json = jsonEncode(OTPs.value); + await _secureStorage.write( + key: otpKey, value: json, aOptions: _getAndroidOptions()); + } + + static Future readOTP() async { + var containsKey = await _secureStorage.containsKey( + key: otpKey, aOptions: _getAndroidOptions()); + if (!containsKey) { + return; + } + + var json = + await _secureStorage.read(key: otpKey, aOptions: _getAndroidOptions()); + + Map data = jsonDecode(json!); + Map map = + data.map((name, data) => MapEntry(name, OTP.fromJson(data))); + + OTPs.value = map; + } + + static Future writeFCMToken(String? token) async { + await _secureStorage.write( + key: fcmKey, value: token, aOptions: _getAndroidOptions()); + } + + static Future readFCMToken() async { + var containsKey = await _secureStorage.containsKey( + key: fcmKey, aOptions: _getAndroidOptions()); + if (!containsKey) { + return null; + } + + return await _secureStorage.read(key: fcmKey, aOptions: _getAndroidOptions()); + } +} diff --git a/app/lib/unlock.dart b/app/lib/unlock.dart new file mode 100644 index 0000000..c6ce3cf --- /dev/null +++ b/app/lib/unlock.dart @@ -0,0 +1,101 @@ +import 'dart:convert'; + +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_settings_screens/flutter_settings_screens.dart'; +import 'package:http/http.dart' as http; +import 'package:vepiot/fcm.dart'; +import 'package:vepiot/unlocker.dart'; + +import 'gen/api/v1/api.pb.dart'; +import 'otp.dart'; + +class UnlockScreen extends StatefulWidget { + final String id; + final String name; + final OTP otp; + + const UnlockScreen( + {required this.id, required this.name, required this.otp, super.key}); + + @override + State createState() => _UnlockScreenState(); +} + +class _UnlockScreenState extends State { + Future handle(bool allow) async { + var deviceId = await FCM.getToken(); + + TOTPResponseType type = TOTPResponseType.TOTP_RESPONSE_TYPE_UNSPECIFIED; + if (allow) { + type = TOTPResponseType.TOTP_RESPONSE_TYPE_ALLOW; + } else { + type = TOTPResponseType.TOTP_RESPONSE_TYPE_DENY; + } + + http.Response resp = await UnlockService.handle(TOTPResponse( + id: widget.id, + deviceId: deviceId, + name: widget.name, + type: type, + ), widget.otp); + + if (mounted && resp.statusCode != 200) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('${resp.statusCode}: ${resp.body}'), + )); + } + + if (mounted) { + Navigator.pop(context); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Unlock - ${widget.otp.username}"), + ), + body: const Center(), + bottomNavigationBar: BottomAppBar( + color: Colors.transparent, + elevation: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: TextButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(Colors.red), + foregroundColor: + MaterialStateProperty.all(Colors.white), + ), + onPressed: () => handle(false), + child: const Text( + 'Deny', + style: TextStyle(fontSize: 30), + ), + ), + ), + Expanded( + child: TextButton( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all(Colors.green), + foregroundColor: + MaterialStateProperty.all(Colors.white), + ), + onPressed: () => handle(true), + child: const Text( + 'Allow', + style: TextStyle(fontSize: 30), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/app/lib/unlocker.dart b/app/lib/unlocker.dart new file mode 100644 index 0000000..7eaf144 --- /dev/null +++ b/app/lib/unlocker.dart @@ -0,0 +1,32 @@ +import 'dart:convert'; + +import 'package:flutter_settings_screens/flutter_settings_screens.dart'; +import 'package:vepiot/otp.dart'; + +import 'gen/api/v1/api.pb.dart'; +import 'package:http/http.dart' as http; + +class UnlockService { + static Future handle(TOTPResponse response, OTP otp) async { + response.totpCode = otp.generateCode(); + + var request = SendTOTPRequest( + response: response, + ); + + if (!Settings.isInitialized) { + await Settings.init(); + } + var uri = Settings.getValue("proxy-url"); + + var resp = await http.post( + Uri.parse('$uri/api.v1.Service/SendTOTP'), + headers: { + 'Content-Type': 'application/json', + }, + body: jsonEncode(request.toProto3Json()), + ); + + return resp; + } +} diff --git a/app/pubspec.lock b/app/pubspec.lock new file mode 100644 index 0000000..2a60b55 --- /dev/null +++ b/app/pubspec.lock @@ -0,0 +1,1034 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "0c80aeab9bc807ab10022cd3b2f4cf2ecdf231949dc1ddd9442406a003f19201" + url: "https://pub.dev" + source: hosted + version: "52.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "3ff770dfff04a67b0863dff205a0936784de1b87a5e99b11c693fc10e66a9ce3" + url: "https://pub.dev" + source: hosted + version: "1.0.12" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: cd8ee83568a77f3ae6b913a36093a1c9b1264e7cb7f834d9ddd2311dade9c1f4 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + args: + dependency: transitive + description: + name: args + sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + async: + dependency: transitive + description: + name: async + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" + source: hosted + version: "2.10.0" + barcode_scan2: + dependency: "direct main" + description: + name: barcode_scan2 + sha256: f9af9252b8f3f5fa446f5456fd45f8871d09f883d8389a1d608b39231bfbc3fa + url: "https://pub.dev" + source: hosted + version: "4.2.3" + base32: + dependency: transitive + description: + name: base32 + sha256: ddad4ebfedf93d4500818ed8e61443b734ffe7cf8a45c668c9b34ef6adde02e2 + url: "https://pub.dev" + source: hosted + version: "2.1.3" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + build_runner: + dependency: "direct main" + description: + name: build_runner + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" + source: hosted + version: "2.3.3" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" + source: hosted + version: "7.2.7" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + url: "https://pub.dev" + source: hosted + version: "8.4.3" + characters: + dependency: transitive + description: + name: characters + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" + source: hosted + version: "1.2.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" + source: hosted + version: "4.4.0" + collection: + dependency: transitive + description: + name: collection + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" + source: hosted + version: "1.17.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" + source: hosted + version: "0.3.3+4" + crypto: + dependency: transitive + description: + name: crypto + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + dbus: + dependency: transitive + description: + name: dbus + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" + source: hosted + version: "0.7.8" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: c129209ba55f3d4272c89fb4a4994c15bea77fb6de63a82d45fb6bc5c94e4355 + url: "https://pub.dev" + source: hosted + version: "2.4.1" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: "5fab93f5b354648efa62e7cc829c90efb68c8796eecf87e0888cae2d5f3accd4" + url: "https://pub.dev" + source: hosted + version: "4.5.2" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "18b35ce111b0a4266abf723c825bcf9d4e2519d13638cc7f06f2a8dd960c75bc" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: dc010a6436333029fba858415fe65887c3fe44d8f6e6ea162bb8d3dd764fbcb6 + url: "https://pub.dev" + source: hosted + version: "14.2.1" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: abda2d766486096eb1c568c7b20aef46180596c8b0708190b929133ff03e0a8d + url: "https://pub.dev" + source: hosted + version: "4.2.10" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "7a0ce957bd2210e8636325152234728874dad039f1c7271ba1be5c752fdc5888" + url: "https://pub.dev" + source: hosted + version: "3.2.11" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" + source: hosted + version: "2.0.1" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + sha256: "293995f94e120c8afce768981bd1fa9c5d6de67c547568e3b42ae2defdcbb4a0" + url: "https://pub.dev" + source: hosted + version: "13.0.0" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" + url: "https://pub.dev" + source: hosted + version: "2.0.7" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: f2afec1f1762c040a349ea2a588e32f442da5d0db3494a52a929a97c9e550bc5 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "736436adaf91552433823f51ce22e098c2f0551db06b6596f58597a25b8ea797" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: ff0768a6700ea1d9620e03518e2e25eac86a8bd07ca3556e9617bfa5ace4bd00 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: b3773190e385a3c8a382007893d678ae95462b3c2279e987b55d140d3b0cb81b + url: "https://pub.dev" + source: hosted + version: "1.0.1" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: "42938e70d4b872e856e678c423cc0e9065d7d294f45bc41fc1981a4eb4beaffe" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: ca89c8059cf439985aa83c59619b3674c7ef6cc2e86943d169a7369d6a69cab5 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + flutter_settings_screens: + dependency: "direct main" + description: + name: flutter_settings_screens + sha256: da028a639710ae9d1d97eb67c2c2e541b7af4e75496104c6d20103f3dc0f2b0a + url: "https://pub.dev" + source: hosted + version: "0.3.3-null-safety+2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + graphs: + dependency: transitive + description: + name: graphs + sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + url: "https://pub.dev" + source: hosted + version: "2.2.0" + http: + dependency: "direct main" + description: + name: http + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" + source: hosted + version: "0.13.5" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + intl: + dependency: transitive + description: + name: intl + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + url: "https://pub.dev" + source: hosted + version: "0.18.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" + source: hosted + version: "4.8.0" + json_serializable: + dependency: "direct main" + description: + name: json_serializable + sha256: dadc08bd61f72559f938dd08ec20dbfec6c709bba83515085ea943d2078d187a + url: "https://pub.dev" + source: hosted + version: "6.6.1" + lints: + dependency: transitive + description: + name: lints + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + local_auth: + dependency: "direct main" + description: + name: local_auth + sha256: "8cea55dca20d1e0efa5480df2d47ae30851e7a24cb8e7d225be7e67ae8485aa4" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + local_auth_android: + dependency: transitive + description: + name: local_auth_android + sha256: ba48fe0e1cae140a0813ce68c2540250d7f573a8ae4d4b6c681b2d2583584953 + url: "https://pub.dev" + source: hosted + version: "1.0.17" + local_auth_ios: + dependency: transitive + description: + name: local_auth_ios + sha256: aa32478d7513066564139af57e11e2cad1bbd535c1efd224a88a8764c5665e3b + url: "https://pub.dev" + source: hosted + version: "1.0.12" + local_auth_platform_interface: + dependency: transitive + description: + name: local_auth_platform_interface + sha256: fbb6973f2fd088e2677f39a5ab550aa1cfbc00997859d5e865569872499d6d61 + url: "https://pub.dev" + source: hosted + version: "1.0.6" + local_auth_windows: + dependency: transitive + description: + name: local_auth_windows + sha256: "888482e4f9ca3560e00bc227ce2badeb4857aad450c42a31c6cfc9dc21e0ccbc" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + logging: + dependency: transitive + description: + name: logging + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" + source: hosted + version: "0.12.13" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" + source: hosted + version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + otp: + dependency: "direct main" + description: + name: otp + sha256: "337fddb07d10df56dc57f3f8a3e1a7e7abe7463cd85e4efc567c4d2bc94d4ed6" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" + source: hosted + version: "1.8.2" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + url: "https://pub.dev" + source: hosted + version: "2.0.12" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + url: "https://pub.dev" + source: hosted + version: "2.0.22" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" + source: hosted + version: "2.1.7" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" + source: hosted + version: "2.1.3" + pedantic: + dependency: transitive + description: + name: pedantic + sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" + source: hosted + version: "2.1.3" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + protobuf: + dependency: "direct main" + description: + name: protobuf + sha256: "01dd9bd0fa02548bf2ceee13545d4a0ec6046459d847b6b061d8a27237108a08" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + provider: + dependency: transitive + description: + name: provider + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" + source: hosted + version: "6.0.5" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: e387077716f80609bb979cd199331033326033ecd1c8f200a90c5f57b1c9f55e + url: "https://pub.dev" + source: hosted + version: "6.3.0" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "82ddd4ab9260c295e6e39612d4ff00390b9a7a21f1bb1da771e2f232d80ab8a1" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + shared_preferences: + dependency: transitive + description: + name: shared_preferences + sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" + url: "https://pub.dev" + source: hosted + version: "2.0.17" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" + url: "https://pub.dev" + source: hosted + version: "2.0.15" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 + url: "https://pub.dev" + source: hosted + version: "2.1.3" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 + url: "https://pub.dev" + source: hosted + version: "2.1.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + url: "https://pub.dev" + source: hosted + version: "2.0.4" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + shelf: + dependency: transitive + description: + name: shelf + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" + source: hosted + version: "1.4.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: c2bea18c95cfa0276a366270afaa2850b09b4a76db95d546f3d003dcc7011298 + url: "https://pub.dev" + source: hosted + version: "1.2.7" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" + source: hosted + version: "0.4.16" + timezone: + dependency: transitive + description: + name: timezone + sha256: "24c8fcdd49a805d95777a39064862133ff816ebfffe0ceff110fb5960e557964" + url: "https://pub.dev" + source: hosted + version: "0.9.1" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" + url: "https://pub.dev" + source: hosted + version: "2.0.14" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + watcher: + dependency: transitive + description: + name: watcher + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" + source: hosted + version: "2.3.0" + win32: + dependency: transitive + description: + name: win32 + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + url: "https://pub.dev" + source: hosted + version: "3.1.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" + source: hosted + version: "0.2.0+3" + xml: + dependency: transitive + description: + name: xml + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" + source: hosted + version: "6.2.2" + yaml: + dependency: transitive + description: + name: yaml + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" + source: hosted + version: "3.1.1" +sdks: + dart: ">=2.19.0 <4.0.0" + flutter: ">=3.0.0" diff --git a/app/pubspec.yaml b/app/pubspec.yaml new file mode 100644 index 0000000..3bf1891 --- /dev/null +++ b/app/pubspec.yaml @@ -0,0 +1,104 @@ +name: vepiot +description: Vepiot +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=2.17.0 <3.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + protobuf: ^2.1.0 + flutter_settings_screens: ^0.3.3-null-safety+2 + otp: ^3.1.3 + flutter_secure_storage: ^7.0.1 + json_annotation: ^4.7.0 + json_serializable: ^6.5.4 + build_runner: ^2.3.3 + firebase_core: ^2.4.1 + firebase_messaging: ^14.2.1 + http: ^0.13.5 + share_plus: ^6.3.0 + barcode_scan2: ^4.2.3 + flutter_local_notifications: ^13.0.0 + local_auth: ^2.1.3 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/auth_proxy/gen/api/v1/api.pb.go b/auth_proxy/gen/api/v1/api.pb.go new file mode 100644 index 0000000..36908a2 --- /dev/null +++ b/auth_proxy/gen/api/v1/api.pb.go @@ -0,0 +1,662 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc (unknown) +// source: api/v1/api.proto + +package api_v1 + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type TOTPResponseType int32 + +const ( + TOTPResponseType_TOTP_RESPONSE_TYPE_UNSPECIFIED TOTPResponseType = 0 + TOTPResponseType_TOTP_RESPONSE_TYPE_ALLOW TOTPResponseType = 1 + TOTPResponseType_TOTP_RESPONSE_TYPE_DENY TOTPResponseType = 2 +) + +// Enum value maps for TOTPResponseType. +var ( + TOTPResponseType_name = map[int32]string{ + 0: "TOTP_RESPONSE_TYPE_UNSPECIFIED", + 1: "TOTP_RESPONSE_TYPE_ALLOW", + 2: "TOTP_RESPONSE_TYPE_DENY", + } + TOTPResponseType_value = map[string]int32{ + "TOTP_RESPONSE_TYPE_UNSPECIFIED": 0, + "TOTP_RESPONSE_TYPE_ALLOW": 1, + "TOTP_RESPONSE_TYPE_DENY": 2, + } +) + +func (x TOTPResponseType) Enum() *TOTPResponseType { + p := new(TOTPResponseType) + *p = x + return p +} + +func (x TOTPResponseType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TOTPResponseType) Descriptor() protoreflect.EnumDescriptor { + return file_api_v1_api_proto_enumTypes[0].Descriptor() +} + +func (TOTPResponseType) Type() protoreflect.EnumType { + return &file_api_v1_api_proto_enumTypes[0] +} + +func (x TOTPResponseType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TOTPResponseType.Descriptor instead. +func (TOTPResponseType) EnumDescriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{0} +} + +type TOTPRequestType int32 + +const ( + TOTPRequestType_TOTP_REQUEST_TYPE_UNSPECIFIED TOTPRequestType = 0 + TOTPRequestType_TOTP_REQUEST_TYPE_REQUEST TOTPRequestType = 1 + TOTPRequestType_TOTP_REQUEST_TYPE_RESPONSE TOTPRequestType = 2 + TOTPRequestType_TOTP_REQUEST_TYPE_CANCEL TOTPRequestType = 3 +) + +// Enum value maps for TOTPRequestType. +var ( + TOTPRequestType_name = map[int32]string{ + 0: "TOTP_REQUEST_TYPE_UNSPECIFIED", + 1: "TOTP_REQUEST_TYPE_REQUEST", + 2: "TOTP_REQUEST_TYPE_RESPONSE", + 3: "TOTP_REQUEST_TYPE_CANCEL", + } + TOTPRequestType_value = map[string]int32{ + "TOTP_REQUEST_TYPE_UNSPECIFIED": 0, + "TOTP_REQUEST_TYPE_REQUEST": 1, + "TOTP_REQUEST_TYPE_RESPONSE": 2, + "TOTP_REQUEST_TYPE_CANCEL": 3, + } +) + +func (x TOTPRequestType) Enum() *TOTPRequestType { + p := new(TOTPRequestType) + *p = x + return p +} + +func (x TOTPRequestType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TOTPRequestType) Descriptor() protoreflect.EnumDescriptor { + return file_api_v1_api_proto_enumTypes[1].Descriptor() +} + +func (TOTPRequestType) Type() protoreflect.EnumType { + return &file_api_v1_api_proto_enumTypes[1] +} + +func (x TOTPRequestType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TOTPRequestType.Descriptor instead. +func (TOTPRequestType) EnumDescriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{1} +} + +type TOTPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type TOTPResponseType `protobuf:"varint,1,opt,name=type,proto3,enum=api.v1.TOTPResponseType" json:"type,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + TotpCode string `protobuf:"bytes,3,opt,name=totp_code,json=totpCode,proto3" json:"totp_code,omitempty"` + DeviceId string `protobuf:"bytes,4,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *TOTPResponse) Reset() { + *x = TOTPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TOTPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TOTPResponse) ProtoMessage() {} + +func (x *TOTPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TOTPResponse.ProtoReflect.Descriptor instead. +func (*TOTPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{0} +} + +func (x *TOTPResponse) GetType() TOTPResponseType { + if x != nil { + return x.Type + } + return TOTPResponseType_TOTP_RESPONSE_TYPE_UNSPECIFIED +} + +func (x *TOTPResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *TOTPResponse) GetTotpCode() string { + if x != nil { + return x.TotpCode + } + return "" +} + +func (x *TOTPResponse) GetDeviceId() string { + if x != nil { + return x.DeviceId + } + return "" +} + +func (x *TOTPResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type SendTOTPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Response *TOTPResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` +} + +func (x *SendTOTPRequest) Reset() { + *x = SendTOTPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendTOTPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendTOTPRequest) ProtoMessage() {} + +func (x *SendTOTPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendTOTPRequest.ProtoReflect.Descriptor instead. +func (*SendTOTPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{1} +} + +func (x *SendTOTPRequest) GetResponse() *TOTPResponse { + if x != nil { + return x.Response + } + return nil +} + +type SendTOTPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SendTOTPResponse) Reset() { + *x = SendTOTPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendTOTPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendTOTPResponse) ProtoMessage() {} + +func (x *SendTOTPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendTOTPResponse.ProtoReflect.Descriptor instead. +func (*SendTOTPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{2} +} + +type GetTOTPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetTOTPRequest) Reset() { + *x = GetTOTPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTOTPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTOTPRequest) ProtoMessage() {} + +func (x *GetTOTPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTOTPRequest.ProtoReflect.Descriptor instead. +func (*GetTOTPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{3} +} + +func (x *GetTOTPRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type GetTOTPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Response *TOTPResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` +} + +func (x *GetTOTPResponse) Reset() { + *x = GetTOTPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTOTPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTOTPResponse) ProtoMessage() {} + +func (x *GetTOTPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTOTPResponse.ProtoReflect.Descriptor instead. +func (*GetTOTPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{4} +} + +func (x *GetTOTPResponse) GetResponse() *TOTPResponse { + if x != nil { + return x.Response + } + return nil +} + +type TOTPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type TOTPRequestType `protobuf:"varint,1,opt,name=type,proto3,enum=api.v1.TOTPRequestType" json:"type,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + ResponseType TOTPResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,proto3,enum=api.v1.TOTPResponseType" json:"response_type,omitempty"` +} + +func (x *TOTPRequest) Reset() { + *x = TOTPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TOTPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TOTPRequest) ProtoMessage() {} + +func (x *TOTPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TOTPRequest.ProtoReflect.Descriptor instead. +func (*TOTPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{5} +} + +func (x *TOTPRequest) GetType() TOTPRequestType { + if x != nil { + return x.Type + } + return TOTPRequestType_TOTP_REQUEST_TYPE_UNSPECIFIED +} + +func (x *TOTPRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *TOTPRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TOTPRequest) GetResponseType() TOTPResponseType { + if x != nil { + return x.ResponseType + } + return TOTPResponseType_TOTP_RESPONSE_TYPE_UNSPECIFIED +} + +var File_api_v1_api_proto protoreflect.FileDescriptor + +var file_api_v1_api_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x06, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x22, 0x9a, 0x01, 0x0a, 0x0c, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x74, + 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, + 0x74, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x43, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x0a, 0x10, + 0x53, 0x65, 0x6e, 0x64, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x43, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x0b, 0x54, 0x4f, 0x54, 0x50, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2a, 0x71, 0x0a, 0x10, 0x54, 0x4f, 0x54, 0x50, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x1e, 0x54, + 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x1c, 0x0a, 0x18, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x1b, 0x0a, + 0x17, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x02, 0x2a, 0x91, 0x01, 0x0a, 0x0f, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, + 0x0a, 0x1d, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x01, + 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x02, + 0x12, 0x1c, 0x0a, 0x18, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x10, 0x03, 0x32, 0x88, + 0x01, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x53, 0x65, + 0x6e, 0x64, 0x54, 0x4f, 0x54, 0x50, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x4f, 0x54, + 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_api_v1_api_proto_rawDescOnce sync.Once + file_api_v1_api_proto_rawDescData = file_api_v1_api_proto_rawDesc +) + +func file_api_v1_api_proto_rawDescGZIP() []byte { + file_api_v1_api_proto_rawDescOnce.Do(func() { + file_api_v1_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_v1_api_proto_rawDescData) + }) + return file_api_v1_api_proto_rawDescData +} + +var file_api_v1_api_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_api_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_api_v1_api_proto_goTypes = []interface{}{ + (TOTPResponseType)(0), // 0: api.v1.TOTPResponseType + (TOTPRequestType)(0), // 1: api.v1.TOTPRequestType + (*TOTPResponse)(nil), // 2: api.v1.TOTPResponse + (*SendTOTPRequest)(nil), // 3: api.v1.SendTOTPRequest + (*SendTOTPResponse)(nil), // 4: api.v1.SendTOTPResponse + (*GetTOTPRequest)(nil), // 5: api.v1.GetTOTPRequest + (*GetTOTPResponse)(nil), // 6: api.v1.GetTOTPResponse + (*TOTPRequest)(nil), // 7: api.v1.TOTPRequest +} +var file_api_v1_api_proto_depIdxs = []int32{ + 0, // 0: api.v1.TOTPResponse.type:type_name -> api.v1.TOTPResponseType + 2, // 1: api.v1.SendTOTPRequest.response:type_name -> api.v1.TOTPResponse + 2, // 2: api.v1.GetTOTPResponse.response:type_name -> api.v1.TOTPResponse + 1, // 3: api.v1.TOTPRequest.type:type_name -> api.v1.TOTPRequestType + 0, // 4: api.v1.TOTPRequest.response_type:type_name -> api.v1.TOTPResponseType + 3, // 5: api.v1.Service.SendTOTP:input_type -> api.v1.SendTOTPRequest + 5, // 6: api.v1.Service.GetTOTP:input_type -> api.v1.GetTOTPRequest + 4, // 7: api.v1.Service.SendTOTP:output_type -> api.v1.SendTOTPResponse + 6, // 8: api.v1.Service.GetTOTP:output_type -> api.v1.GetTOTPResponse + 7, // [7:9] is the sub-list for method output_type + 5, // [5:7] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_api_v1_api_proto_init() } +func file_api_v1_api_proto_init() { + if File_api_v1_api_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_api_v1_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TOTPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendTOTPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendTOTPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTOTPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTOTPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TOTPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_v1_api_proto_rawDesc, + NumEnums: 2, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_api_v1_api_proto_goTypes, + DependencyIndexes: file_api_v1_api_proto_depIdxs, + EnumInfos: file_api_v1_api_proto_enumTypes, + MessageInfos: file_api_v1_api_proto_msgTypes, + }.Build() + File_api_v1_api_proto = out.File + file_api_v1_api_proto_rawDesc = nil + file_api_v1_api_proto_goTypes = nil + file_api_v1_api_proto_depIdxs = nil +} diff --git a/auth_proxy/gen/api/v1/v1connect/api.connect.go b/auth_proxy/gen/api/v1/v1connect/api.connect.go new file mode 100644 index 0000000..d7db229 --- /dev/null +++ b/auth_proxy/gen/api/v1/v1connect/api.connect.go @@ -0,0 +1,108 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: api/v1/api.proto + +package v1connect + +import ( + context "context" + errors "errors" + connect_go "github.com/bufbuild/connect-go" + v1 "github.com/kilimnik/vepiot/auth_proxy/gen/api/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect_go.IsAtLeastVersion0_1_0 + +const ( + // ServiceName is the fully-qualified name of the Service service. + ServiceName = "api.v1.Service" +) + +// ServiceClient is a client for the api.v1.Service service. +type ServiceClient interface { + SendTOTP(context.Context, *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) + GetTOTP(context.Context, *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) +} + +// NewServiceClient constructs a client for the api.v1.Service service. By default, it uses the +// Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends +// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or +// connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) ServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &serviceClient{ + sendTOTP: connect_go.NewClient[v1.SendTOTPRequest, v1.SendTOTPResponse]( + httpClient, + baseURL+"/api.v1.Service/SendTOTP", + opts..., + ), + getTOTP: connect_go.NewClient[v1.GetTOTPRequest, v1.GetTOTPResponse]( + httpClient, + baseURL+"/api.v1.Service/GetTOTP", + opts..., + ), + } +} + +// serviceClient implements ServiceClient. +type serviceClient struct { + sendTOTP *connect_go.Client[v1.SendTOTPRequest, v1.SendTOTPResponse] + getTOTP *connect_go.Client[v1.GetTOTPRequest, v1.GetTOTPResponse] +} + +// SendTOTP calls api.v1.Service.SendTOTP. +func (c *serviceClient) SendTOTP(ctx context.Context, req *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) { + return c.sendTOTP.CallUnary(ctx, req) +} + +// GetTOTP calls api.v1.Service.GetTOTP. +func (c *serviceClient) GetTOTP(ctx context.Context, req *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) { + return c.getTOTP.CallUnary(ctx, req) +} + +// ServiceHandler is an implementation of the api.v1.Service service. +type ServiceHandler interface { + SendTOTP(context.Context, *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) + GetTOTP(context.Context, *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) +} + +// NewServiceHandler builds an HTTP handler from the service implementation. It returns the path on +// which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewServiceHandler(svc ServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { + mux := http.NewServeMux() + mux.Handle("/api.v1.Service/SendTOTP", connect_go.NewUnaryHandler( + "/api.v1.Service/SendTOTP", + svc.SendTOTP, + opts..., + )) + mux.Handle("/api.v1.Service/GetTOTP", connect_go.NewUnaryHandler( + "/api.v1.Service/GetTOTP", + svc.GetTOTP, + opts..., + )) + return "/api.v1.Service/", mux +} + +// UnimplementedServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedServiceHandler struct{} + +func (UnimplementedServiceHandler) SendTOTP(context.Context, *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.Service.SendTOTP is not implemented")) +} + +func (UnimplementedServiceHandler) GetTOTP(context.Context, *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.Service.GetTOTP is not implemented")) +} diff --git a/auth_proxy/go.mod b/auth_proxy/go.mod new file mode 100644 index 0000000..5eabfd9 --- /dev/null +++ b/auth_proxy/go.mod @@ -0,0 +1,14 @@ +module github.com/kilimnik/vepiot/auth_proxy + +go 1.18 + +require ( + github.com/bufbuild/connect-go v1.4.1 + github.com/golang/protobuf v1.5.0 + golang.org/x/net v0.4.0 +) + +require ( + golang.org/x/text v0.5.0 // indirect + google.golang.org/protobuf v1.28.1 +) diff --git a/auth_proxy/go.sum b/auth_proxy/go.sum new file mode 100644 index 0000000..671d79c --- /dev/null +++ b/auth_proxy/go.sum @@ -0,0 +1,14 @@ +github.com/bufbuild/connect-go v1.4.1 h1:6usL3JGjKhxQpvDlizP7u8VfjAr1JkckcAUbrdcbgNY= +github.com/bufbuild/connect-go v1.4.1/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/auth_proxy/main.go b/auth_proxy/main.go new file mode 100644 index 0000000..144af3b --- /dev/null +++ b/auth_proxy/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "context" + "errors" + "net/http" + "time" + + "github.com/bufbuild/connect-go" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + + api "github.com/kilimnik/vepiot/auth_proxy/gen/api/v1" // generated by protoc-gen-go + "github.com/kilimnik/vepiot/auth_proxy/gen/api/v1/v1connect" // generated by protoc-gen-connect-go +) + +type TOTP struct { + time time.Time + response api.TOTPResponse +} + +type Device struct { + id string +} + +type Server struct { + TOTPs map[string]*TOTP +} + +func (s *Server) SendTOTP( + ctx context.Context, + req *connect.Request[api.SendTOTPRequest], +) (*connect.Response[api.SendTOTPResponse], error) { + if req.Msg.GetResponse() == nil { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("response can't be empty")) + } + + s.TOTPs[req.Msg.Response.Id] = &TOTP{ + time: time.Now(), + response: *req.Msg.GetResponse(), + } + + res := connect.NewResponse(&api.SendTOTPResponse{}) + + return res, nil +} + +func (s *Server) GetTOTP( + ctx context.Context, + req *connect.Request[api.GetTOTPRequest], +) (*connect.Response[api.GetTOTPResponse], error) { + if len(req.Msg.Id) == 0 { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("id can't be empty")) + } + + totp, ok := s.TOTPs[req.Msg.Id] + if !ok { + return nil, connect.NewError(connect.CodeNotFound, errors.New("id has no codes")) + } + + delete(s.TOTPs, req.Msg.Id) + + res := connect.NewResponse(&api.GetTOTPResponse{ + Response: &totp.response, + }) + + return res, nil +} + +func main() { + server := &Server{ + TOTPs: make(map[string]*TOTP), + } + + mux := http.NewServeMux() + path, handler := v1connect.NewServiceHandler(server) + mux.Handle(path, handler) + http.ListenAndServe( + "0.0.0.0:8080", + // Use h2c so we can serve HTTP/2 without TLS. + h2c.NewHandler(mux, &http2.Server{}), + ) +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..be40e14 --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs-master": { + "locked": { + "lastModified": 1671743101, + "narHash": "sha256-7OB8hAGT5MxeYGwXmbIVI3KW2ld+Xt0MySOdY3BooAI=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "372858814dd803d576ca1df8ca6ee58235bdd872", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1671359686, + "narHash": "sha256-3MpC6yZo+Xn9cPordGz2/ii6IJpP2n8LE8e/ebUXLrs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "04f574a1c0fde90b51bf68198e2297ca4e7cccf4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs-master": "nixpkgs-master", + "nixpkgs-unstable": "nixpkgs-unstable" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..0cc363b --- /dev/null +++ b/flake.nix @@ -0,0 +1,48 @@ +{ + inputs = { + nixpkgs-master.url = "github:nixos/nixpkgs/master"; + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, flake-utils, nixpkgs-unstable, nixpkgs-master, ... }@inputs: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs-master = nixpkgs-master.legacyPackages.${system}.appendOverlays [ + + ]; + + pkgs = import nixpkgs-unstable ({ + inherit system; + + overlays = [ + ]; + + config.allowUnfree = true; + }); + + in + { + devShell = pkgs.pkgs.mkShell { + + buildInputs = with pkgs; + [ + protobuf + stdenv + go_1_18 + buf + cmake + vault-bin + protoc-gen-go + pkgs-master.protoc-gen-connect-go + ]; + shellHook = '' + export CFLAGS="-I${pkgs.glibc.dev}/include" + export LDFLAGS="-L${pkgs.glibc}/lib" + [ -n "$(go env GOBIN)" ] && export PATH="$(go env GOBIN):''${PATH}" + [ -n "$(go env GOPATH)" ] && export PATH="$(go env GOPATH)/bin:''${PATH}" + ''; + }; + + }); +} diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000..5afd557 --- /dev/null +++ b/logo.svg @@ -0,0 +1,146 @@ + + + + diff --git a/vault_plugin/.gitignore b/vault_plugin/.gitignore new file mode 100644 index 0000000..3583229 --- /dev/null +++ b/vault_plugin/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +.idea +.vscode + +/vault \ No newline at end of file diff --git a/vault_plugin/Makefile b/vault_plugin/Makefile new file mode 100644 index 0000000..022dcf7 --- /dev/null +++ b/vault_plugin/Makefile @@ -0,0 +1,32 @@ +GOARCH = amd64 + +UNAME = $(shell uname -s) + +ifndef OS + ifeq ($(UNAME), Linux) + OS = linux + else ifeq ($(UNAME), Darwin) + OS = darwin + endif +endif + +.DEFAULT_GOAL := all + +all: fmt build start + +build: + GOOS=$(OS) GOARCH="$(GOARCH)" go build -o vault/plugins/vepiot cmd/vepiot/main.go + +start: + vault server -dev -dev-root-token-id=root -dev-plugin-dir=./vault/plugins + +enable: + vault auth enable -path=vepiot vepiot + +clean: + rm -f ./vault/plugins/vepiot + +fmt: + go fmt $$(go list ./...) + +.PHONY: build clean fmt start enable diff --git a/vault_plugin/README.md b/vault_plugin/README.md new file mode 100644 index 0000000..b42fab4 --- /dev/null +++ b/vault_plugin/README.md @@ -0,0 +1,44 @@ +# Vault Mock Secrets Plugin + +Mock is an example secrets engine plugin for [HashiCorp Vault](https://www.vaultproject.io/). It is meant for demonstration purposes only and should never be used in production. + +## Usage + +All commands can be run using the provided [Makefile](./Makefile). However, it may be instructive to look at the commands to gain a greater understanding of how Vault registers plugins. Using the Makefile will result in running the Vault server in `dev` mode. Do not run Vault in `dev` mode in production. The `dev` server allows you to configure the plugin directory as a flag, and automatically registers plugin binaries in that directory. In production, plugin binaries must be manually registered. + +This will build the plugin binary and start the Vault dev server: + +``` +# Build Mock plugin and start Vault dev server with plugin automatically registered +$ make +``` + +Now open a new terminal window and run the following commands: + +``` +# Open a new terminal window and export Vault dev server http address +$ export VAULT_ADDR='http://127.0.0.1:8200' + +# Enable the Mock plugin +$ make enable + +# Create a new user, "john" with password, "password" +$ vault write auth/mock-auth/user/john password=password +``` + +To login using the mock auth method: + +``` +$ vault write auth/mock-auth/login user=john password=password + +Key Value +--- ----- +token s.PRjzJuKTWKlYc1jbGPLh5ghX +token_accessor oyQxJRrWnhR8bhoZY0XfMq7b +token_duration 30s +token_renewable true +token_policies ["default" "my-policy" "other-policy"] +identity_policies [] +policies ["default" "my-policy" "other-policy"] +token_meta_user john +``` diff --git a/vault_plugin/backend.go b/vault_plugin/backend.go new file mode 100644 index 0000000..9cdff02 --- /dev/null +++ b/vault_plugin/backend.go @@ -0,0 +1,443 @@ +package auth + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "sort" + "strings" + "time" + + firebase "firebase.google.com/go" + "firebase.google.com/go/messaging" + "github.com/bufbuild/connect-go" + "github.com/google/uuid" + "github.com/hashicorp/vault/sdk/framework" + "github.com/hashicorp/vault/sdk/helper/policyutil" + "github.com/hashicorp/vault/sdk/logical" + api_v1 "github.com/kilimnik/vepiot/vault_plugin/gen/api/v1" + "github.com/kilimnik/vepiot/vault_plugin/gen/api/v1/v1connect" + "github.com/mdp/qrterminal/v3" + "github.com/pquerna/otp/totp" + "google.golang.org/api/option" +) + +type User struct { + Secret string +} + +type Auth struct { + Policies []string + ServiceAccount string + Users map[string]*User +} + +// backend wraps the backend framework and adds a map for storing key value pairs. +type backend struct { + *framework.Backend + + auths map[string]*Auth +} + +var _ logical.Factory = Factory + +// Factory configures and returns Mock backends +func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { + b, err := newBackend() + if err != nil { + return nil, err + } + + if conf == nil { + return nil, fmt.Errorf("configuration passed into backend is nil") + } + + if err := b.Setup(ctx, conf); err != nil { + return nil, err + } + + return b, nil +} + +func newBackend() (*backend, error) { + b := &backend{ + auths: make(map[string]*Auth), + } + + b.Backend = &framework.Backend{ + Help: strings.TrimSpace(pluginHelp), + BackendType: logical.TypeCredential, + PathsSpecial: &logical.Paths{ + Unauthenticated: []string{ + "login", + }, + }, + Paths: framework.PathAppend( + []*framework.Path{ + b.pathLogin(), + b.pathAuthsList(), + }, + b.pathAuths(), + ), + } + + return b, nil +} + +func (b *backend) pathLogin() *framework.Path { + return &framework.Path{ + Pattern: "login$", + Fields: map[string]*framework.FieldSchema{ + "name": { + Required: true, + Type: framework.TypeString, + Description: "Auth name to login", + }, + }, + Operations: map[logical.Operation]framework.OperationHandler{ + logical.UpdateOperation: &framework.PathOperation{ + Callback: b.handleLogin, + Summary: "Log in using auth method", + }, + }, + } +} + +func (b *backend) handleLogin(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + name := data.Get("name").(string) + if name == "" { + return logical.ErrorResponse("name must be provided"), nil + } + + auth, ok := b.auths[name] + if !ok { + return nil, logical.ErrPermissionDenied + } + + opts := []option.ClientOption{ + option.WithCredentialsJSON([]byte(auth.ServiceAccount)), + } + app, err := firebase.NewApp(context.Background(), nil, opts...) + if err != nil { + return logical.ErrorResponse("error in initializing firebase app: %s", err.Error()), err + } + + messageingClient, err := app.Messaging(ctx) + if err != nil { + return logical.ErrorResponse("error getting Messaging client: %v\n", err.Error()), err + } + + id := (uuid.New()).String() + + proto := &api_v1.TOTPRequest{ + Type: api_v1.TOTPRequestType_TOTP_REQUEST_TYPE_REQUEST, + Id: id, + Name: name, + } + + logialErr, err := SendFirebaseMessage( + ctx, + proto, + auth, + messageingClient, + ) + if err != nil { + return logialErr, err + } + + defer SendCancelMessage(context.Background(), auth, messageingClient, id, name) + + response, err := RetrieveTOTPLoop(ctx, id) + if err != nil { + return logical.ErrorResponse("retrieve totp failed %s", err.Error()), err + } + + user := auth.Users[response.GetResponse().GetDeviceId()] + if !totp.Validate(response.GetResponse().GetTotpCode(), user.Secret) { + return nil, logical.ErrPermissionDenied + } + + if response.GetResponse().GetType() != api_v1.TOTPResponseType_TOTP_RESPONSE_TYPE_ALLOW { + return nil, logical.ErrPermissionDenied + } + + proto = &api_v1.TOTPRequest{ + Type: api_v1.TOTPRequestType_TOTP_REQUEST_TYPE_RESPONSE, + Id: id, + Name: name, + } + + logialErr, err = SendFirebaseMessage( + ctx, + proto, + auth, + messageingClient, + ) + if err != nil { + return logialErr, err + } + + // Compose the response + resp := &logical.Response{ + Auth: &logical.Auth{ + InternalData: map[string]interface{}{ + "totp": response.GetResponse().GetTotpCode(), + }, + // Policies can be passed in as a parameter to the request + Policies: auth.Policies, + Metadata: map[string]string{ + "name": name, + "user": response.GetResponse().GetDeviceId(), + }, + // Lease options can be passed in as parameters to the request + LeaseOptions: logical.LeaseOptions{ + TTL: 30 * time.Second, + MaxTTL: 15 * time.Minute, + Renewable: false, + }, + }, + } + + return resp, nil +} + +func SendCancelMessage( + ctx context.Context, + auth *Auth, + messageingClient *messaging.Client, + id string, + name string, +) (*logical.Response, error) { + proto := &api_v1.TOTPRequest{ + Type: api_v1.TOTPRequestType_TOTP_REQUEST_TYPE_CANCEL, + Id: id, + Name: name, + } + + logialErr, err := SendFirebaseMessage( + ctx, + proto, + auth, + messageingClient, + ) + + return logialErr, err +} + +func SendFirebaseMessage( + ctx context.Context, + proto *api_v1.TOTPRequest, + auth *Auth, + messageingClient *messaging.Client, +) (*logical.Response, error) { + protoJson, err := json.Marshal(proto) + if err != nil { + return logical.ErrorResponse("failed to marshal proto %s", err.Error()), err + } + + keys := make([]string, 0, len(auth.Users)) + for k := range auth.Users { + keys = append(keys, k) + } + + msg := &messaging.MulticastMessage{ + Data: map[string]string{ + "proto": string(protoJson), + }, + Tokens: keys, + } + + _, err = messageingClient.SendMulticast(ctx, msg) + if err != nil { + return logical.ErrorResponse("failed to send message to clients %s", err.Error()), err + } + + return nil, nil +} + +func RetrieveTOTPLoop( + ctx context.Context, + id string, +) (*api_v1.GetTOTPResponse, error) { + client := v1connect.NewServiceClient(http.DefaultClient, "http://127.0.0.1:8080") + + for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + if resp, err := RetrieveTOTP(ctx, client, id); err == nil { + return resp, nil + } else if connect.CodeOf(err) != connect.CodeNotFound { + return nil, err + } + time.Sleep(1 * time.Second) + } + } +} + +func RetrieveTOTP( + ctx context.Context, + client v1connect.ServiceClient, + id string, +) (*api_v1.GetTOTPResponse, error) { + res, err := client.GetTOTP( + ctx, + connect.NewRequest(&api_v1.GetTOTPRequest{Id: id}), + ) + if err != nil { + return nil, err + } + + return res.Msg, nil +} + +func (b *backend) pathAuths() []*framework.Path { + return []*framework.Path{ + { + Pattern: "auths/" + framework.GenericNameRegex("name"), + + Fields: map[string]*framework.FieldSchema{ + "name": { + Required: true, + Type: framework.TypeString, + Description: "Specifies the auth name", + }, + "service_account": { + Required: true, + Type: framework.TypeString, + Description: "Specifies the firebase service account used to push cloud messages", + }, + "policies": { + Required: true, + Type: framework.TypeCommaStringSlice, + Description: "Specifies the policies", + }, + "firebase_device_ids": { + Required: true, + Type: framework.TypeCommaStringSlice, + Description: "Specifies the device ids to send the notification to", + }, + }, + + Operations: map[logical.Operation]framework.OperationHandler{ + logical.CreateOperation: &framework.PathOperation{ + Callback: b.handleAuthWrite, + Summary: "Add a new auth method.", + }, + logical.DeleteOperation: &framework.PathOperation{ + Callback: b.handleAuthDelete, + Summary: "Deletes an auth method.", + }, + }, + + ExistenceCheck: b.handleExistenceCheck, + }, + } +} + +func (b *backend) handleExistenceCheck(ctx context.Context, req *logical.Request, data *framework.FieldData) (bool, error) { + name := data.Get("name").(string) + _, ok := b.auths[name] + + return ok, nil +} + +func (b *backend) pathAuthsList() *framework.Path { + return &framework.Path{ + Pattern: "auths/?$", + Operations: map[logical.Operation]framework.OperationHandler{ + logical.ListOperation: &framework.PathOperation{ + Callback: b.handleAuthsList, + Summary: "List existing auths.", + }, + }, + } +} + +func (b *backend) handleAuthsList(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + authsList := make([]string, len(b.auths)) + + i := 0 + for u := range b.auths { + authsList[i] = u + i++ + } + + sort.Strings(authsList) + + return logical.ListResponse(authsList), nil +} + +func (b *backend) handleAuthWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + name := data.Get("name").(string) + if name == "" { + return logical.ErrorResponse("'name': name must be provided"), nil + } + + serviceAccount := data.Get("service_account").(string) + if serviceAccount == "" { + return logical.ErrorResponse("'service_account': service account must be provided"), nil + } + + policies := policyutil.ParsePolicies(data.Get("policies")) + if len(policies) == 0 { + return logical.ErrorResponse("'policies': at least one policy must be provided"), nil + } + + firebaseDeviceIds := ParseList(data.Get("firebase_device_ids")) + if len(firebaseDeviceIds) == 0 { + return logical.ErrorResponse("'firebase_device_ids': at least one firebase device id must be provided"), nil + } + + // Store kv pairs in map at specified path + totpQrCodes := make(map[string]interface{}) + users := make(map[string]*User) + for _, device := range firebaseDeviceIds { + key, err := totp.Generate(totp.GenerateOpts{ + Issuer: "Vepiot Vault", + AccountName: name, + }) + if err != nil { + return nil, err + } + + users[device] = &User{ + Secret: key.Secret(), + } + + buf := new(bytes.Buffer) + qrterminal.Generate(key.URL(), qrterminal.L, buf) + totpQrCodes[device] = ".\n" + buf.String() + } + + b.auths[name] = &Auth{ + Policies: policies, + ServiceAccount: serviceAccount, + Users: users, + } + + resp := &logical.Response{ + Data: totpQrCodes, + } + + return resp, nil +} + +func (b *backend) handleAuthDelete(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + name := data.Get("name").(string) + if name == "" { + return logical.ErrorResponse("name must be provided"), nil + } + + // Remove entry for specified path + delete(b.auths, name) + + return nil, nil +} + +const pluginHelp = ` +This plugin adds an authentication method which needs an external validation during usage +` diff --git a/vault_plugin/cmd/vepiot/main.go b/vault_plugin/cmd/vepiot/main.go new file mode 100644 index 0000000..ed0c0fa --- /dev/null +++ b/vault_plugin/cmd/vepiot/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "os" + + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/vault/api" + "github.com/hashicorp/vault/sdk/plugin" + auth "github.com/kilimnik/vepiot/vault_plugin" +) + +func main() { + apiClientMeta := &api.PluginAPIClientMeta{} + flags := apiClientMeta.FlagSet() + flags.Parse(os.Args[1:]) + + tlsConfig := apiClientMeta.GetTLSConfig() + tlsProviderFunc := api.VaultPluginTLSProvider(tlsConfig) + + err := plugin.Serve(&plugin.ServeOpts{ + BackendFactoryFunc: auth.Factory, + TLSProviderFunc: tlsProviderFunc, + }) + if err != nil { + logger := hclog.New(&hclog.LoggerOptions{}) + + logger.Error("plugin shutting down", "error", err) + os.Exit(1) + } +} diff --git a/vault_plugin/gen/api/v1/api.pb.go b/vault_plugin/gen/api/v1/api.pb.go new file mode 100644 index 0000000..36908a2 --- /dev/null +++ b/vault_plugin/gen/api/v1/api.pb.go @@ -0,0 +1,662 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc (unknown) +// source: api/v1/api.proto + +package api_v1 + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type TOTPResponseType int32 + +const ( + TOTPResponseType_TOTP_RESPONSE_TYPE_UNSPECIFIED TOTPResponseType = 0 + TOTPResponseType_TOTP_RESPONSE_TYPE_ALLOW TOTPResponseType = 1 + TOTPResponseType_TOTP_RESPONSE_TYPE_DENY TOTPResponseType = 2 +) + +// Enum value maps for TOTPResponseType. +var ( + TOTPResponseType_name = map[int32]string{ + 0: "TOTP_RESPONSE_TYPE_UNSPECIFIED", + 1: "TOTP_RESPONSE_TYPE_ALLOW", + 2: "TOTP_RESPONSE_TYPE_DENY", + } + TOTPResponseType_value = map[string]int32{ + "TOTP_RESPONSE_TYPE_UNSPECIFIED": 0, + "TOTP_RESPONSE_TYPE_ALLOW": 1, + "TOTP_RESPONSE_TYPE_DENY": 2, + } +) + +func (x TOTPResponseType) Enum() *TOTPResponseType { + p := new(TOTPResponseType) + *p = x + return p +} + +func (x TOTPResponseType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TOTPResponseType) Descriptor() protoreflect.EnumDescriptor { + return file_api_v1_api_proto_enumTypes[0].Descriptor() +} + +func (TOTPResponseType) Type() protoreflect.EnumType { + return &file_api_v1_api_proto_enumTypes[0] +} + +func (x TOTPResponseType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TOTPResponseType.Descriptor instead. +func (TOTPResponseType) EnumDescriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{0} +} + +type TOTPRequestType int32 + +const ( + TOTPRequestType_TOTP_REQUEST_TYPE_UNSPECIFIED TOTPRequestType = 0 + TOTPRequestType_TOTP_REQUEST_TYPE_REQUEST TOTPRequestType = 1 + TOTPRequestType_TOTP_REQUEST_TYPE_RESPONSE TOTPRequestType = 2 + TOTPRequestType_TOTP_REQUEST_TYPE_CANCEL TOTPRequestType = 3 +) + +// Enum value maps for TOTPRequestType. +var ( + TOTPRequestType_name = map[int32]string{ + 0: "TOTP_REQUEST_TYPE_UNSPECIFIED", + 1: "TOTP_REQUEST_TYPE_REQUEST", + 2: "TOTP_REQUEST_TYPE_RESPONSE", + 3: "TOTP_REQUEST_TYPE_CANCEL", + } + TOTPRequestType_value = map[string]int32{ + "TOTP_REQUEST_TYPE_UNSPECIFIED": 0, + "TOTP_REQUEST_TYPE_REQUEST": 1, + "TOTP_REQUEST_TYPE_RESPONSE": 2, + "TOTP_REQUEST_TYPE_CANCEL": 3, + } +) + +func (x TOTPRequestType) Enum() *TOTPRequestType { + p := new(TOTPRequestType) + *p = x + return p +} + +func (x TOTPRequestType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TOTPRequestType) Descriptor() protoreflect.EnumDescriptor { + return file_api_v1_api_proto_enumTypes[1].Descriptor() +} + +func (TOTPRequestType) Type() protoreflect.EnumType { + return &file_api_v1_api_proto_enumTypes[1] +} + +func (x TOTPRequestType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TOTPRequestType.Descriptor instead. +func (TOTPRequestType) EnumDescriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{1} +} + +type TOTPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type TOTPResponseType `protobuf:"varint,1,opt,name=type,proto3,enum=api.v1.TOTPResponseType" json:"type,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + TotpCode string `protobuf:"bytes,3,opt,name=totp_code,json=totpCode,proto3" json:"totp_code,omitempty"` + DeviceId string `protobuf:"bytes,4,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *TOTPResponse) Reset() { + *x = TOTPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TOTPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TOTPResponse) ProtoMessage() {} + +func (x *TOTPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TOTPResponse.ProtoReflect.Descriptor instead. +func (*TOTPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{0} +} + +func (x *TOTPResponse) GetType() TOTPResponseType { + if x != nil { + return x.Type + } + return TOTPResponseType_TOTP_RESPONSE_TYPE_UNSPECIFIED +} + +func (x *TOTPResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *TOTPResponse) GetTotpCode() string { + if x != nil { + return x.TotpCode + } + return "" +} + +func (x *TOTPResponse) GetDeviceId() string { + if x != nil { + return x.DeviceId + } + return "" +} + +func (x *TOTPResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type SendTOTPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Response *TOTPResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` +} + +func (x *SendTOTPRequest) Reset() { + *x = SendTOTPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendTOTPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendTOTPRequest) ProtoMessage() {} + +func (x *SendTOTPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendTOTPRequest.ProtoReflect.Descriptor instead. +func (*SendTOTPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{1} +} + +func (x *SendTOTPRequest) GetResponse() *TOTPResponse { + if x != nil { + return x.Response + } + return nil +} + +type SendTOTPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SendTOTPResponse) Reset() { + *x = SendTOTPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendTOTPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendTOTPResponse) ProtoMessage() {} + +func (x *SendTOTPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendTOTPResponse.ProtoReflect.Descriptor instead. +func (*SendTOTPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{2} +} + +type GetTOTPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetTOTPRequest) Reset() { + *x = GetTOTPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTOTPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTOTPRequest) ProtoMessage() {} + +func (x *GetTOTPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTOTPRequest.ProtoReflect.Descriptor instead. +func (*GetTOTPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{3} +} + +func (x *GetTOTPRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type GetTOTPResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Response *TOTPResponse `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` +} + +func (x *GetTOTPResponse) Reset() { + *x = GetTOTPResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTOTPResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTOTPResponse) ProtoMessage() {} + +func (x *GetTOTPResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTOTPResponse.ProtoReflect.Descriptor instead. +func (*GetTOTPResponse) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{4} +} + +func (x *GetTOTPResponse) GetResponse() *TOTPResponse { + if x != nil { + return x.Response + } + return nil +} + +type TOTPRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type TOTPRequestType `protobuf:"varint,1,opt,name=type,proto3,enum=api.v1.TOTPRequestType" json:"type,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + ResponseType TOTPResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,proto3,enum=api.v1.TOTPResponseType" json:"response_type,omitempty"` +} + +func (x *TOTPRequest) Reset() { + *x = TOTPRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v1_api_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TOTPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TOTPRequest) ProtoMessage() {} + +func (x *TOTPRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_api_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TOTPRequest.ProtoReflect.Descriptor instead. +func (*TOTPRequest) Descriptor() ([]byte, []int) { + return file_api_v1_api_proto_rawDescGZIP(), []int{5} +} + +func (x *TOTPRequest) GetType() TOTPRequestType { + if x != nil { + return x.Type + } + return TOTPRequestType_TOTP_REQUEST_TYPE_UNSPECIFIED +} + +func (x *TOTPRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *TOTPRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TOTPRequest) GetResponseType() TOTPResponseType { + if x != nil { + return x.ResponseType + } + return TOTPResponseType_TOTP_RESPONSE_TYPE_UNSPECIFIED +} + +var File_api_v1_api_proto protoreflect.FileDescriptor + +var file_api_v1_api_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x06, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x22, 0x9a, 0x01, 0x0a, 0x0c, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x74, + 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, + 0x74, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x43, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x0a, 0x10, + 0x53, 0x65, 0x6e, 0x64, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x43, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x0b, 0x54, 0x4f, 0x54, 0x50, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x2a, 0x71, 0x0a, 0x10, 0x54, 0x4f, 0x54, 0x50, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x1e, 0x54, + 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x1c, 0x0a, 0x18, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x1b, 0x0a, + 0x17, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4e, 0x59, 0x10, 0x02, 0x2a, 0x91, 0x01, 0x0a, 0x0f, 0x54, + 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, + 0x0a, 0x1d, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x01, + 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x02, + 0x12, 0x1c, 0x0a, 0x18, 0x54, 0x4f, 0x54, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x10, 0x03, 0x32, 0x88, + 0x01, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x53, 0x65, + 0x6e, 0x64, 0x54, 0x4f, 0x54, 0x50, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x4f, 0x54, + 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x4f, 0x54, 0x50, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_api_v1_api_proto_rawDescOnce sync.Once + file_api_v1_api_proto_rawDescData = file_api_v1_api_proto_rawDesc +) + +func file_api_v1_api_proto_rawDescGZIP() []byte { + file_api_v1_api_proto_rawDescOnce.Do(func() { + file_api_v1_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_v1_api_proto_rawDescData) + }) + return file_api_v1_api_proto_rawDescData +} + +var file_api_v1_api_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_api_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_api_v1_api_proto_goTypes = []interface{}{ + (TOTPResponseType)(0), // 0: api.v1.TOTPResponseType + (TOTPRequestType)(0), // 1: api.v1.TOTPRequestType + (*TOTPResponse)(nil), // 2: api.v1.TOTPResponse + (*SendTOTPRequest)(nil), // 3: api.v1.SendTOTPRequest + (*SendTOTPResponse)(nil), // 4: api.v1.SendTOTPResponse + (*GetTOTPRequest)(nil), // 5: api.v1.GetTOTPRequest + (*GetTOTPResponse)(nil), // 6: api.v1.GetTOTPResponse + (*TOTPRequest)(nil), // 7: api.v1.TOTPRequest +} +var file_api_v1_api_proto_depIdxs = []int32{ + 0, // 0: api.v1.TOTPResponse.type:type_name -> api.v1.TOTPResponseType + 2, // 1: api.v1.SendTOTPRequest.response:type_name -> api.v1.TOTPResponse + 2, // 2: api.v1.GetTOTPResponse.response:type_name -> api.v1.TOTPResponse + 1, // 3: api.v1.TOTPRequest.type:type_name -> api.v1.TOTPRequestType + 0, // 4: api.v1.TOTPRequest.response_type:type_name -> api.v1.TOTPResponseType + 3, // 5: api.v1.Service.SendTOTP:input_type -> api.v1.SendTOTPRequest + 5, // 6: api.v1.Service.GetTOTP:input_type -> api.v1.GetTOTPRequest + 4, // 7: api.v1.Service.SendTOTP:output_type -> api.v1.SendTOTPResponse + 6, // 8: api.v1.Service.GetTOTP:output_type -> api.v1.GetTOTPResponse + 7, // [7:9] is the sub-list for method output_type + 5, // [5:7] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_api_v1_api_proto_init() } +func file_api_v1_api_proto_init() { + if File_api_v1_api_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_api_v1_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TOTPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendTOTPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SendTOTPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTOTPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTOTPResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v1_api_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TOTPRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_v1_api_proto_rawDesc, + NumEnums: 2, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_api_v1_api_proto_goTypes, + DependencyIndexes: file_api_v1_api_proto_depIdxs, + EnumInfos: file_api_v1_api_proto_enumTypes, + MessageInfos: file_api_v1_api_proto_msgTypes, + }.Build() + File_api_v1_api_proto = out.File + file_api_v1_api_proto_rawDesc = nil + file_api_v1_api_proto_goTypes = nil + file_api_v1_api_proto_depIdxs = nil +} diff --git a/vault_plugin/gen/api/v1/v1connect/api.connect.go b/vault_plugin/gen/api/v1/v1connect/api.connect.go new file mode 100644 index 0000000..8b7e382 --- /dev/null +++ b/vault_plugin/gen/api/v1/v1connect/api.connect.go @@ -0,0 +1,108 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: api/v1/api.proto + +package v1connect + +import ( + context "context" + errors "errors" + connect_go "github.com/bufbuild/connect-go" + v1 "github.com/kilimnik/vepiot/vault_plugin/gen/api/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect_go.IsAtLeastVersion0_1_0 + +const ( + // ServiceName is the fully-qualified name of the Service service. + ServiceName = "api.v1.Service" +) + +// ServiceClient is a client for the api.v1.Service service. +type ServiceClient interface { + SendTOTP(context.Context, *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) + GetTOTP(context.Context, *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) +} + +// NewServiceClient constructs a client for the api.v1.Service service. By default, it uses the +// Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends +// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or +// connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) ServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &serviceClient{ + sendTOTP: connect_go.NewClient[v1.SendTOTPRequest, v1.SendTOTPResponse]( + httpClient, + baseURL+"/api.v1.Service/SendTOTP", + opts..., + ), + getTOTP: connect_go.NewClient[v1.GetTOTPRequest, v1.GetTOTPResponse]( + httpClient, + baseURL+"/api.v1.Service/GetTOTP", + opts..., + ), + } +} + +// serviceClient implements ServiceClient. +type serviceClient struct { + sendTOTP *connect_go.Client[v1.SendTOTPRequest, v1.SendTOTPResponse] + getTOTP *connect_go.Client[v1.GetTOTPRequest, v1.GetTOTPResponse] +} + +// SendTOTP calls api.v1.Service.SendTOTP. +func (c *serviceClient) SendTOTP(ctx context.Context, req *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) { + return c.sendTOTP.CallUnary(ctx, req) +} + +// GetTOTP calls api.v1.Service.GetTOTP. +func (c *serviceClient) GetTOTP(ctx context.Context, req *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) { + return c.getTOTP.CallUnary(ctx, req) +} + +// ServiceHandler is an implementation of the api.v1.Service service. +type ServiceHandler interface { + SendTOTP(context.Context, *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) + GetTOTP(context.Context, *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) +} + +// NewServiceHandler builds an HTTP handler from the service implementation. It returns the path on +// which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewServiceHandler(svc ServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { + mux := http.NewServeMux() + mux.Handle("/api.v1.Service/SendTOTP", connect_go.NewUnaryHandler( + "/api.v1.Service/SendTOTP", + svc.SendTOTP, + opts..., + )) + mux.Handle("/api.v1.Service/GetTOTP", connect_go.NewUnaryHandler( + "/api.v1.Service/GetTOTP", + svc.GetTOTP, + opts..., + )) + return "/api.v1.Service/", mux +} + +// UnimplementedServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedServiceHandler struct{} + +func (UnimplementedServiceHandler) SendTOTP(context.Context, *connect_go.Request[v1.SendTOTPRequest]) (*connect_go.Response[v1.SendTOTPResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.Service.SendTOTP is not implemented")) +} + +func (UnimplementedServiceHandler) GetTOTP(context.Context, *connect_go.Request[v1.GetTOTPRequest]) (*connect_go.Response[v1.GetTOTPResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("api.v1.Service.GetTOTP is not implemented")) +} diff --git a/vault_plugin/go.mod b/vault_plugin/go.mod new file mode 100644 index 0000000..909e8b5 --- /dev/null +++ b/vault_plugin/go.mod @@ -0,0 +1,74 @@ +module github.com/kilimnik/vepiot/vault_plugin + +go 1.18 + +require ( + firebase.google.com/go v3.13.0+incompatible + github.com/bufbuild/connect-go v1.4.1 + github.com/golang/protobuf v1.5.2 + github.com/google/uuid v1.3.0 + github.com/hashicorp/go-hclog v0.14.1 + github.com/hashicorp/vault/api v1.0.5-0.20210325191337-ac5500471f36 + github.com/hashicorp/vault/sdk v0.1.14-0.20210325185647-d3758c9bd369 + github.com/mdp/qrterminal/v3 v3.0.0 + github.com/pquerna/otp v1.4.0 + google.golang.org/api v0.107.0 + google.golang.org/protobuf v1.28.1 +) + +require ( + cloud.google.com/go v0.105.0 // indirect + cloud.google.com/go/compute v1.14.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/firestore v1.9.0 // indirect + cloud.google.com/go/iam v0.8.0 // indirect + cloud.google.com/go/longrunning v0.3.0 // indirect + cloud.google.com/go/storage v1.27.0 // indirect + github.com/armon/go-metrics v0.3.3 // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect + github.com/fatih/color v1.7.0 // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/snappy v0.0.1 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.1 // indirect + github.com/hashicorp/go-immutable-radix v1.1.0 // indirect + github.com/hashicorp/go-kms-wrapping/entropy v0.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/hashicorp/go-plugin v1.0.1 // indirect + github.com/hashicorp/go-retryablehttp v0.6.6 // indirect + github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/go-version v1.2.0 // indirect + github.com/hashicorp/golang-lru v0.5.3 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/mattn/go-colorable v0.1.6 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.0.0 // indirect + github.com/mitchellh/mapstructure v1.3.2 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/oklog/run v1.0.0 // indirect + github.com/pierrec/lz4 v2.5.2+incompatible // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect + golang.org/x/text v0.5.0 // indirect + golang.org/x/time v0.1.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect + google.golang.org/grpc v1.51.0 // indirect + gopkg.in/square/go-jose.v2 v2.5.1 // indirect + rsc.io/qr v0.2.0 // indirect +) diff --git a/vault_plugin/go.sum b/vault_plugin/go.sum new file mode 100644 index 0000000..4a71036 --- /dev/null +++ b/vault_plugin/go.sum @@ -0,0 +1,456 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go/compute v1.14.0 h1:hfm2+FfxVmnRlh6LpB7cg1ZNU+5edAHmW679JePztk0= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/firestore v1.9.0 h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4= +firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= +github.com/armon/go-metrics v0.3.3 h1:a9F4rlj7EWWrbj7BYw8J8+x+ZZkJeqzNyRk8hdPF+ro= +github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bufbuild/connect-go v1.4.1 h1:6usL3JGjKhxQpvDlizP7u8VfjAr1JkckcAUbrdcbgNY= +github.com/bufbuild/connect-go v1.4.1/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200709052629-daa8e1ccc0bc/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20200319182547-c7ad2b866182/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE= +github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8= +github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.1.0 h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc= +github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-kms-wrapping/entropy v0.1.0 h1:xuTi5ZwjimfpvpL09jDE71smCBRpnF5xfo871BSX4gs= +github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE= +github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY= +github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= +github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE= +github.com/hashicorp/vault/api v1.0.5-0.20210325191337-ac5500471f36 h1:ApRbXrIwsFwWKS5pxg+pSCY/4aqPUkwWO86+dADlq/0= +github.com/hashicorp/vault/api v1.0.5-0.20210325191337-ac5500471f36/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221530-14615acda45f/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= +github.com/hashicorp/vault/sdk v0.1.14-0.20210325185647-d3758c9bd369 h1:jy9dbpwTiEDOF/nemRLfj4s3ijHxy3pXO5k/ATnpSW0= +github.com/hashicorp/vault/sdk v0.1.14-0.20210325185647-d3758c9bd369/go.mod h1:cAGI4nVnEfAyMeqt9oB+Mase8DNn3qA/LDNHURiwssY= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= +github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mdp/qrterminal v1.0.1/go.mod h1:Z33WhxQe9B6CdW37HaVqcRKzP+kByF3q/qLxOGe12xQ= +github.com/mdp/qrterminal/v3 v3.0.0 h1:ywQqLRBXWTktytQNDKFjhAvoGkLVN3J2tAFZ0kMd9xQ= +github.com/mdp/qrterminal/v3 v3.0.0/go.mod h1:NJpfAs7OAm77Dy8EkWrtE4aq+cE6McoLXlBqXQEwvE0= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= +github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= +github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.107.0 h1:I2SlFjD8ZWabaIFOfeEDg3pf0BHJDh6iYQ1ic3Yu/UU= +google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= +rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs= diff --git a/vault_plugin/helper.go b/vault_plugin/helper.go new file mode 100644 index 0000000..082c059 --- /dev/null +++ b/vault_plugin/helper.go @@ -0,0 +1,22 @@ +package auth + +import "strings" + +func ParseList(raw interface{}) []string { + if raw == nil { + return []string{} + } + + var slice []string + switch raw.(type) { + case string: + if raw.(string) == "" { + return []string{} + } + slice = strings.Split(raw.(string), ",") + case []string: + slice = raw.([]string) + } + + return slice +}