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 0000000..2bc1284 Binary files /dev/null and b/app/android/app/src/main/res/drawable-hdpi/ic_stat_logo.png differ 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 0000000..53c7fdb Binary files /dev/null and b/app/android/app/src/main/res/drawable-mdpi/ic_stat_logo.png differ diff --git a/app/android/app/src/main/res/drawable-v21/launch_background.xml b/app/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..b0a05a7 --- /dev/null +++ b/app/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + 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 0000000..91eb198 Binary files /dev/null and b/app/android/app/src/main/res/drawable-xhdpi/ic_stat_logo.png differ diff --git a/app/android/app/src/main/res/drawable-xxhdpi/ic_stat_logo.png b/app/android/app/src/main/res/drawable-xxhdpi/ic_stat_logo.png new file mode 100644 index 0000000..5071269 Binary files /dev/null and b/app/android/app/src/main/res/drawable-xxhdpi/ic_stat_logo.png differ 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 0000000..3c804bc Binary files /dev/null and b/app/android/app/src/main/res/drawable-xxxhdpi/ic_stat_logo.png differ 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 0000000..dc9ada4 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..7353c41 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ 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 0000000..797d452 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ 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 0000000..6ed2d93 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ 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 0000000..4cd7b00 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ 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 0000000..fe73094 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..321773c Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ 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 0000000..502f463 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ 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 0000000..0ec3034 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ 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 0000000..e9f5fea Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..84ac32a Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..8953cba Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ 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 0000000..0467bf1 Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ 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 0000000..9da19ea Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ 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 0000000..9da19ea Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ 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 0000000..9da19ea Binary files /dev/null and b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ 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 +}