Android Support (#166)
1. Add vpnservice tauri plugin for android. 2. add workflow for android. 3. Easytier Core support android, allow set tun fd.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
name: Audit
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/audit.yml"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/audit.yml"
|
||||
- "**/Cargo.lock"
|
||||
- "**/Cargo.toml"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: rustsec/audit-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/check.yml"
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.toml"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/check.yml"
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.toml"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt
|
||||
- run: cargo fmt --all -- --check
|
||||
|
||||
clippy:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy
|
||||
- name: install webkit2gtk
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y webkit2gtk-4.1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo clippy --all-targets --all-features -- -D warnings
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: install webkit2gtk
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y webkit2gtk-4.1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo test --all-targets --all-features -- -D warnings
|
||||
@@ -0,0 +1,17 @@
|
||||
/.vs
|
||||
.DS_Store
|
||||
.Thumbs.db
|
||||
*.sublime*
|
||||
.idea/
|
||||
debug.log
|
||||
package-lock.json
|
||||
.vscode/settings.json
|
||||
yarn.lock
|
||||
|
||||
/.tauri
|
||||
/target
|
||||
Cargo.lock
|
||||
node_modules/
|
||||
|
||||
dist-js
|
||||
dist
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "tauri-plugin-vpnservice"
|
||||
version = "0.0.0"
|
||||
authors = [ "You" ]
|
||||
description = ""
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
exclude = ["/examples", "/webview-dist", "/webview-src", "/node_modules"]
|
||||
links = "tauri-plugin-vpnservice"
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0.0-beta.23" }
|
||||
serde = "1.0"
|
||||
thiserror = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-plugin = { version = "2.0.0-beta.18", features = ["build"] }
|
||||
@@ -0,0 +1 @@
|
||||
# Tauri Plugin vpnservice
|
||||
@@ -0,0 +1,2 @@
|
||||
/build
|
||||
/.tauri
|
||||
@@ -0,0 +1,45 @@
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.plugin.vpnservice"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
targetSdk = 34
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation("androidx.core:core-ktx:1.9.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.0")
|
||||
implementation("com.google.android.material:material:1.7.0")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
implementation(project(":tauri-android"))
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,2 @@
|
||||
include ':tauri-android'
|
||||
project(':tauri-android').projectDir = new File('./.tauri/tauri-api')
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.plugin.vpnservice
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.plugin.vpnservice", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.plugin.vpnservice
|
||||
|
||||
import android.util.Log
|
||||
|
||||
class Example {
|
||||
fun pong(value: String): String {
|
||||
Log.i("Pong", value)
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.plugin.vpnservice
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import android.net.IpPrefix
|
||||
import android.os.Build
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.os.Bundle
|
||||
import java.net.InetAddress
|
||||
import java.util.Arrays
|
||||
|
||||
import app.tauri.plugin.JSObject
|
||||
|
||||
fun stringToIpPrefix(ipPrefixString: String): IpPrefix {
|
||||
val parts = ipPrefixString.split("/")
|
||||
if (parts.size != 2) throw IllegalArgumentException("Invalid IP prefix string")
|
||||
|
||||
val address = InetAddress.getByName(parts[0])
|
||||
val prefixLength = parts[1].toInt()
|
||||
|
||||
return IpPrefix(address, prefixLength)
|
||||
}
|
||||
|
||||
class TauriVpnService : VpnService() {
|
||||
companion object {
|
||||
@JvmField var triggerCallback: (String, JSObject) -> Unit = { _, _ -> }
|
||||
@JvmField var self: TauriVpnService? = null
|
||||
|
||||
const val IPV4_ADDR = "IPV4_ADDR"
|
||||
const val ROUTES = "ROUTES"
|
||||
const val DNS = "DNS"
|
||||
const val DISALLOWED_APPLICATIONS = "DISALLOWED_APPLICATIONS"
|
||||
const val MTU = "MTU"
|
||||
}
|
||||
|
||||
private lateinit var vpnInterface: ParcelFileDescriptor
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
println("vpn on start command ${intent?.getExtras()} $intent")
|
||||
var args = intent?.getExtras()
|
||||
|
||||
vpnInterface = createVpnInterface(args)
|
||||
println("vpn created ${vpnInterface.fd}")
|
||||
|
||||
var event_data = JSObject()
|
||||
event_data.put("fd", vpnInterface.fd)
|
||||
triggerCallback("vpn_service_start", event_data)
|
||||
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
self = this
|
||||
println("vpn on create")
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
println("vpn on destroy")
|
||||
self = null
|
||||
super.onDestroy()
|
||||
disconnect()
|
||||
}
|
||||
|
||||
override fun onRevoke() {
|
||||
println("vpn on revoke")
|
||||
self = null
|
||||
super.onRevoke()
|
||||
disconnect()
|
||||
}
|
||||
|
||||
private fun disconnect() {
|
||||
triggerCallback("vpn_service_stop", JSObject())
|
||||
vpnInterface.close()
|
||||
}
|
||||
|
||||
private fun createVpnInterface(args: Bundle?): ParcelFileDescriptor {
|
||||
var builder = Builder()
|
||||
.setSession("TauriVpnService")
|
||||
.setBlocking(false)
|
||||
|
||||
var mtu = args?.getInt(MTU) ?: 1500
|
||||
var ipv4Addr = args?.getString(IPV4_ADDR) ?: "10.126.126.1/24"
|
||||
var dns = args?.getString(DNS) ?: "114.114.114.114"
|
||||
var routes = args?.getStringArray(ROUTES) ?: emptyArray()
|
||||
var disallowedApplications = args?.getStringArray(DISALLOWED_APPLICATIONS) ?: emptyArray()
|
||||
|
||||
println("vpn create vpn interface. mtu: $mtu, ipv4Addr: $ipv4Addr, dns:" +
|
||||
"$dns, routes: ${java.util.Arrays.toString(routes)}," +
|
||||
"disallowedApplications: ${java.util.Arrays.toString(disallowedApplications)}")
|
||||
|
||||
val ipParts = ipv4Addr.split("/")
|
||||
if (ipParts.size != 2) throw IllegalArgumentException("Invalid IP addr string")
|
||||
builder.addAddress(ipParts[0], ipParts[1].toInt())
|
||||
|
||||
builder.setMtu(mtu)
|
||||
builder.addDnsServer(dns)
|
||||
|
||||
for (route in routes) {
|
||||
builder.addRoute(stringToIpPrefix(route))
|
||||
}
|
||||
|
||||
for (app in disallowedApplications) {
|
||||
builder.addDisallowedApplication(app)
|
||||
}
|
||||
|
||||
return builder.also {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
it.setMetered(false)
|
||||
}
|
||||
}
|
||||
.establish()
|
||||
?: throw IllegalStateException("Failed to init VpnService")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.plugin.vpnservice
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import app.tauri.annotation.Command
|
||||
import app.tauri.annotation.InvokeArg
|
||||
import app.tauri.annotation.TauriPlugin
|
||||
import app.tauri.plugin.Invoke
|
||||
import app.tauri.plugin.JSObject
|
||||
import app.tauri.plugin.Plugin
|
||||
import android.webkit.WebView
|
||||
|
||||
@InvokeArg
|
||||
class PingArgs {
|
||||
var value: String? = null
|
||||
}
|
||||
|
||||
@InvokeArg
|
||||
class StartVpnArgs {
|
||||
var ipv4Addr: String? = null
|
||||
var routes: Array<String> = emptyArray()
|
||||
var dns: String? = null
|
||||
var disallowedApplications: Array<String> = emptyArray()
|
||||
var mtu: Int? = null
|
||||
}
|
||||
|
||||
@TauriPlugin
|
||||
class VpnServicePlugin(private val activity: Activity) : Plugin(activity) {
|
||||
private val implementation = Example()
|
||||
|
||||
override fun load(webView: WebView) {
|
||||
println("load vpn service plugin")
|
||||
TauriVpnService.triggerCallback = { event, data ->
|
||||
println("vpn: triggerCallback $event $data")
|
||||
trigger(event, data)
|
||||
}
|
||||
}
|
||||
|
||||
@Command
|
||||
fun ping(invoke: Invoke) {
|
||||
val args = invoke.parseArgs(PingArgs::class.java)
|
||||
|
||||
val ret = JSObject()
|
||||
ret.put("value", implementation.pong(args.value ?: "default value :("))
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
|
||||
@Command
|
||||
fun prepareVpn(invoke: Invoke) {
|
||||
println("prepare vpn in plugin")
|
||||
val it = VpnService.prepare(activity)
|
||||
var ret = JSObject()
|
||||
if (it != null) {
|
||||
activity.startActivityForResult(it, 0x0f)
|
||||
ret.put("errorMsg", "again")
|
||||
}
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
|
||||
@Command
|
||||
fun startVpn(invoke: Invoke) {
|
||||
val args = invoke.parseArgs(StartVpnArgs::class.java)
|
||||
println("start vpn in plugin, args: $args")
|
||||
|
||||
TauriVpnService.self?.onRevoke()
|
||||
|
||||
val it = VpnService.prepare(activity)
|
||||
var ret = JSObject()
|
||||
if (it != null) {
|
||||
ret.put("errorMsg", "need_prepare")
|
||||
} else {
|
||||
var intent = Intent(activity, TauriVpnService::class.java)
|
||||
intent.putExtra(TauriVpnService.IPV4_ADDR, args.ipv4Addr)
|
||||
intent.putExtra(TauriVpnService.ROUTES, args.routes)
|
||||
intent.putExtra(TauriVpnService.DNS, args.dns)
|
||||
intent.putExtra(TauriVpnService.DISALLOWED_APPLICATIONS, args.disallowedApplications)
|
||||
intent.putExtra(TauriVpnService.MTU, args.mtu)
|
||||
|
||||
activity.startService(intent)
|
||||
}
|
||||
invoke.resolve(ret)
|
||||
}
|
||||
|
||||
@Command
|
||||
fun stopVpn(invoke: Invoke) {
|
||||
println("stop vpn in plugin")
|
||||
TauriVpnService.self?.onRevoke()
|
||||
activity.stopService(Intent(activity, TauriVpnService::class.java))
|
||||
println("stop vpn in plugin end")
|
||||
invoke.resolve(JSObject())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.plugin.vpnservice
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
const COMMANDS: &[&str] = &[
|
||||
"ping",
|
||||
"prepare_vpn",
|
||||
"start_vpn",
|
||||
"stop_vpn",
|
||||
"register_listener",
|
||||
];
|
||||
|
||||
fn main() {
|
||||
tauri_plugin::Builder::new(COMMANDS)
|
||||
.android_path("android")
|
||||
.ios_path("ios")
|
||||
.build();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
|
||||
export async function ping(value: string): Promise<string | null> {
|
||||
return await invoke<{ value?: string }>('plugin:vpnservice|ping', {
|
||||
payload: {
|
||||
value,
|
||||
},
|
||||
}).then((r) => (r.value ? r.value : null));
|
||||
}
|
||||
|
||||
export interface InvokeResponse {
|
||||
errorMsg?: string;
|
||||
}
|
||||
|
||||
export interface StartVpnRequest {
|
||||
ipv4Addr?: string;
|
||||
routes?: string[];
|
||||
dns?: string;
|
||||
disallowedApplications?: string[];
|
||||
mtu?: number;
|
||||
}
|
||||
|
||||
export async function prepare_vpn(): Promise<InvokeResponse | null> {
|
||||
return await invoke<InvokeResponse>('plugin:vpnservice|prepare_vpn', {})
|
||||
}
|
||||
|
||||
export async function start_vpn(request: StartVpnRequest): Promise<InvokeResponse | null> {
|
||||
return await invoke<InvokeResponse>('plugin:vpnservice|start_vpn', {
|
||||
...request,
|
||||
})
|
||||
}
|
||||
|
||||
export async function stop_vpn(): Promise<InvokeResponse | null> {
|
||||
return await invoke<InvokeResponse>('plugin:vpnservice|stop_vpn', {})
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/config/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
||||
Package.resolved
|
||||
@@ -0,0 +1,31 @@
|
||||
// swift-tools-version:5.3
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "tauri-plugin-vpnservice",
|
||||
platforms: [
|
||||
.iOS(.v13),
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "tauri-plugin-vpnservice",
|
||||
type: .static,
|
||||
targets: ["tauri-plugin-vpnservice"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(name: "Tauri", path: "../.tauri/tauri-api")
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.target(
|
||||
name: "tauri-plugin-vpnservice",
|
||||
dependencies: [
|
||||
.byName(name: "Tauri")
|
||||
],
|
||||
path: "Sources")
|
||||
]
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
# Tauri Plugin vpnservice
|
||||
|
||||
A description of this package.
|
||||
@@ -0,0 +1,20 @@
|
||||
import SwiftRs
|
||||
import Tauri
|
||||
import UIKit
|
||||
import WebKit
|
||||
|
||||
class PingArgs: Decodable {
|
||||
let value: String?
|
||||
}
|
||||
|
||||
class ExamplePlugin: Plugin {
|
||||
@objc public func ping(_ invoke: Invoke) throws {
|
||||
let args = try invoke.parseArgs(PingArgs.self)
|
||||
invoke.resolve(["value": args.value ?? ""])
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("init_plugin_vpnservice")
|
||||
func initPlugin() -> Plugin {
|
||||
return ExamplePlugin()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import XCTest
|
||||
@testable import ExamplePlugin
|
||||
|
||||
final class ExamplePluginTests: XCTestCase {
|
||||
func testExample() throws {
|
||||
let plugin = ExamplePlugin()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "tauri-plugin-vpnservice-api",
|
||||
"version": "0.0.0",
|
||||
"author": "You",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"types": "./dist-js/index.d.ts",
|
||||
"main": "./dist-js/index.cjs",
|
||||
"module": "./dist-js/index.js",
|
||||
"exports": {
|
||||
"types": "./dist-js/index.d.ts",
|
||||
"import": "./dist-js/index.js",
|
||||
"require": "./dist-js/index.cjs"
|
||||
},
|
||||
"files": [
|
||||
"dist-js",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"prepublishOnly": "yarn build",
|
||||
"pretest": "yarn build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": ">=2.0.0-beta.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
"rollup": "^4.9.6",
|
||||
"typescript": "^5.3.3",
|
||||
"tslib": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
"$schema" = "../../schemas/schema.json"
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-ping"
|
||||
description = "Enables the ping command without any pre-configured scope."
|
||||
commands.allow = ["ping"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-ping"
|
||||
description = "Denies the ping command without any pre-configured scope."
|
||||
commands.deny = ["ping"]
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
"$schema" = "../../schemas/schema.json"
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-prepare-vpn"
|
||||
description = "Enables the prepare_vpn command without any pre-configured scope."
|
||||
commands.allow = ["prepare_vpn"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-prepare-vpn"
|
||||
description = "Denies the prepare_vpn command without any pre-configured scope."
|
||||
commands.deny = ["prepare_vpn"]
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
"$schema" = "../../schemas/schema.json"
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-register-listener"
|
||||
description = "Enables the register_listener command without any pre-configured scope."
|
||||
commands.allow = ["register_listener"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-register-listener"
|
||||
description = "Denies the register_listener command without any pre-configured scope."
|
||||
commands.deny = ["register_listener"]
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
"$schema" = "../../schemas/schema.json"
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-start-vpn"
|
||||
description = "Enables the start_vpn command without any pre-configured scope."
|
||||
commands.allow = ["start_vpn"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-start-vpn"
|
||||
description = "Denies the start_vpn command without any pre-configured scope."
|
||||
commands.deny = ["start_vpn"]
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated - DO NOT EDIT!
|
||||
|
||||
"$schema" = "../../schemas/schema.json"
|
||||
|
||||
[[permission]]
|
||||
identifier = "allow-stop-vpn"
|
||||
description = "Enables the stop_vpn command without any pre-configured scope."
|
||||
commands.allow = ["stop_vpn"]
|
||||
|
||||
[[permission]]
|
||||
identifier = "deny-stop-vpn"
|
||||
description = "Denies the stop_vpn command without any pre-configured scope."
|
||||
commands.deny = ["stop_vpn"]
|
||||
@@ -0,0 +1,146 @@
|
||||
## Default Permission
|
||||
|
||||
Default permissions for the plugin
|
||||
|
||||
- `allow-ping`
|
||||
- `allow-start-vpn`
|
||||
|
||||
### Permission Table
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Identifier</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:allow-ping`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the ping command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:deny-ping`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the ping command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:allow-prepare-vpn`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the prepare_vpn command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:deny-prepare-vpn`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the prepare_vpn command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:allow-register-listener`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the register_listener command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:deny-register-listener`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the register_listener command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:allow-start-vpn`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the start_vpn command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:deny-start-vpn`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the start_vpn command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:allow-stop-vpn`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the stop_vpn command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`vpnservice:deny-stop-vpn`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the stop_vpn command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -0,0 +1,3 @@
|
||||
[default]
|
||||
description = "Default permissions for the plugin"
|
||||
permissions = ["allow-ping", "allow-start-vpn"]
|
||||
@@ -0,0 +1,377 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "PermissionFile",
|
||||
"description": "Permission file that can define a default permission, a set of permissions or a list of inlined permissions.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"default": {
|
||||
"description": "The default permission set for the plugin",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DefaultPermission"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"set": {
|
||||
"description": "A list of permissions sets defined",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionSet"
|
||||
}
|
||||
},
|
||||
"permission": {
|
||||
"description": "A list of inlined permissions",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Permission"
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"DefaultPermission": {
|
||||
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"permissions"
|
||||
],
|
||||
"properties": {
|
||||
"version": {
|
||||
"description": "The version of the permission.",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint64",
|
||||
"minimum": 1.0
|
||||
},
|
||||
"description": {
|
||||
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"permissions": {
|
||||
"description": "All permissions this set contains.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PermissionSet": {
|
||||
"description": "A set of direct permissions grouped together under a new name.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"identifier",
|
||||
"permissions"
|
||||
],
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "A unique identifier for the permission.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Human-readable description of what the permission does.",
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"description": "All permissions this set contains.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionKind"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Permission": {
|
||||
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identifier"
|
||||
],
|
||||
"properties": {
|
||||
"version": {
|
||||
"description": "The version of the permission.",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint64",
|
||||
"minimum": 1.0
|
||||
},
|
||||
"identifier": {
|
||||
"description": "A unique identifier for the permission.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"commands": {
|
||||
"description": "Allowed or denied commands when using this permission.",
|
||||
"default": {
|
||||
"allow": [],
|
||||
"deny": []
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Commands"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scope": {
|
||||
"description": "Allowed or denied scoped when using this permission.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Scopes"
|
||||
}
|
||||
]
|
||||
},
|
||||
"platforms": {
|
||||
"description": "Target platforms this permission applies. By default all platforms are affected by this permission.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Target"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Commands": {
|
||||
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow": {
|
||||
"description": "Allowed command.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"description": "Denied command, which takes priority.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Scopes": {
|
||||
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allow": {
|
||||
"description": "Data that defines what is allowed by the scope.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Value": {
|
||||
"description": "All supported ACL values.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Represents a null JSON value.",
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`bool`].",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "Represents a valid ACL [`Number`].",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Number"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`String`].",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Represents a list of other [`Value`]s.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Represents a map of [`String`] keys to [`Value`]s.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/Value"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Number": {
|
||||
"description": "A valid ACL number.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Represents an [`i64`].",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
{
|
||||
"description": "Represents a [`f64`].",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Target": {
|
||||
"description": "Platform target.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "MacOS.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"macOS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Windows.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"windows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Linux.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Android.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "iOS.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"iOS"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionKind": {
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "allow-ping -> Enables the ping command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"allow-ping"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "deny-ping -> Denies the ping command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"deny-ping"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "allow-prepare-vpn -> Enables the prepare_vpn command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"allow-prepare-vpn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "deny-prepare-vpn -> Denies the prepare_vpn command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"deny-prepare-vpn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "allow-register-listener -> Enables the register_listener command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"allow-register-listener"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "deny-register-listener -> Denies the register_listener command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"deny-register-listener"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "allow-start-vpn -> Enables the start_vpn command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"allow-start-vpn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "deny-start-vpn -> Denies the start_vpn command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"deny-start-vpn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "allow-stop-vpn -> Enables the stop_vpn command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"allow-stop-vpn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "deny-stop-vpn -> Denies the stop_vpn command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"deny-stop-vpn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "default -> Default permissions for the plugin",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+308
@@ -0,0 +1,308 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@tauri-apps/api':
|
||||
specifier: '>=2.0.0-beta.6'
|
||||
version: 2.0.0-beta.14
|
||||
devDependencies:
|
||||
'@rollup/plugin-typescript':
|
||||
specifier: ^11.1.6
|
||||
version: 11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.5.3)
|
||||
rollup:
|
||||
specifier: ^4.9.6
|
||||
version: 4.18.1
|
||||
tslib:
|
||||
specifier: ^2.6.2
|
||||
version: 2.6.3
|
||||
typescript:
|
||||
specifier: ^5.3.3
|
||||
version: 5.5.3
|
||||
|
||||
packages:
|
||||
|
||||
'@rollup/plugin-typescript@11.1.6':
|
||||
resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^2.14.0||^3.0.0||^4.0.0
|
||||
tslib: '*'
|
||||
typescript: '>=3.7.0'
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
tslib:
|
||||
optional: true
|
||||
|
||||
'@rollup/pluginutils@5.1.0':
|
||||
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.18.1':
|
||||
resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.18.1':
|
||||
resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.18.1':
|
||||
resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.18.1':
|
||||
resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.18.1':
|
||||
resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.18.1':
|
||||
resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.18.1':
|
||||
resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.18.1':
|
||||
resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.18.1':
|
||||
resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.18.1':
|
||||
resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.18.1':
|
||||
resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@tauri-apps/api@2.0.0-beta.14':
|
||||
resolution: {integrity: sha512-YLYgHqdwWswr4Y70+hRzaLD6kLIUgHhE3shLXNquPiTaQ9+cX3Q2dB0AFfqsua6NXYFNe7LfkmMzaqEzqv3yQg==}
|
||||
engines: {node: '>= 18.18', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||
|
||||
'@types/estree@1.0.5':
|
||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||
|
||||
estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
|
||||
fsevents@2.3.3:
|
||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-core-module@2.14.0:
|
||||
resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
path-parse@1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
|
||||
picomatch@2.3.1:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
resolve@1.22.8:
|
||||
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
|
||||
hasBin: true
|
||||
|
||||
rollup@4.18.1:
|
||||
resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
tslib@2.6.3:
|
||||
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
|
||||
|
||||
typescript@5.5.3:
|
||||
resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
snapshots:
|
||||
|
||||
'@rollup/plugin-typescript@11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.5.3)':
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.1.0(rollup@4.18.1)
|
||||
resolve: 1.22.8
|
||||
typescript: 5.5.3
|
||||
optionalDependencies:
|
||||
rollup: 4.18.1
|
||||
tslib: 2.6.3
|
||||
|
||||
'@rollup/pluginutils@5.1.0(rollup@4.18.1)':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
optionalDependencies:
|
||||
rollup: 4.18.1
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.18.1':
|
||||
optional: true
|
||||
|
||||
'@tauri-apps/api@2.0.0-beta.14': {}
|
||||
|
||||
'@types/estree@1.0.5': {}
|
||||
|
||||
estree-walker@2.0.2: {}
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
is-core-module@2.14.0:
|
||||
dependencies:
|
||||
hasown: 2.0.2
|
||||
|
||||
path-parse@1.0.7: {}
|
||||
|
||||
picomatch@2.3.1: {}
|
||||
|
||||
resolve@1.22.8:
|
||||
dependencies:
|
||||
is-core-module: 2.14.0
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
|
||||
rollup@4.18.1:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.18.1
|
||||
'@rollup/rollup-android-arm64': 4.18.1
|
||||
'@rollup/rollup-darwin-arm64': 4.18.1
|
||||
'@rollup/rollup-darwin-x64': 4.18.1
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.18.1
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.18.1
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-arm64-musl': 4.18.1
|
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-x64-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-x64-musl': 4.18.1
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.18.1
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.18.1
|
||||
'@rollup/rollup-win32-x64-msvc': 4.18.1
|
||||
fsevents: 2.3.3
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0: {}
|
||||
|
||||
tslib@2.6.3: {}
|
||||
|
||||
typescript@5.5.3: {}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { readFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { cwd } from 'process'
|
||||
import typescript from '@rollup/plugin-typescript'
|
||||
|
||||
const pkg = JSON.parse(readFileSync(join(cwd(), 'package.json'), 'utf8'))
|
||||
|
||||
export default {
|
||||
input: 'guest-js/index.ts',
|
||||
output: [
|
||||
{
|
||||
file: pkg.exports.import,
|
||||
format: 'esm'
|
||||
},
|
||||
{
|
||||
file: pkg.exports.require,
|
||||
format: 'cjs'
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
typescript({
|
||||
declaration: true,
|
||||
declarationDir: `./${pkg.exports.import.split('/')[0]}`
|
||||
})
|
||||
],
|
||||
external: [
|
||||
/^@tauri-apps\/api/,
|
||||
...Object.keys(pkg.dependencies || {}),
|
||||
...Object.keys(pkg.peerDependencies || {})
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use serde::{ser::Serializer, Serialize};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
#[cfg(mobile)]
|
||||
#[error(transparent)]
|
||||
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
|
||||
}
|
||||
|
||||
impl Serialize for Error {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(self.to_string().as_ref())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
use tauri::{
|
||||
plugin::{Builder, TauriPlugin},
|
||||
Runtime,
|
||||
};
|
||||
|
||||
#[cfg(mobile)]
|
||||
use tauri::Manager;
|
||||
|
||||
#[cfg(mobile)]
|
||||
mod mobile;
|
||||
|
||||
#[cfg(mobile)]
|
||||
use mobile::Vpnservice;
|
||||
|
||||
mod error;
|
||||
mod models;
|
||||
|
||||
pub use error::{Error, Result};
|
||||
|
||||
/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the vpnservice APIs.
|
||||
#[cfg(mobile)]
|
||||
pub trait VpnserviceExt<R: Runtime> {
|
||||
fn vpnservice(&self) -> &Vpnservice<R>;
|
||||
}
|
||||
|
||||
#[cfg(mobile)]
|
||||
impl<R: Runtime, T: Manager<R>> crate::VpnserviceExt<R> for T {
|
||||
fn vpnservice(&self) -> &Vpnservice<R> {
|
||||
self.state::<Vpnservice<R>>().inner()
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the plugin.
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("vpnservice")
|
||||
.setup(|_app, _api| {
|
||||
#[cfg(mobile)]
|
||||
{
|
||||
let vpnservice = mobile::init(_app, _api)?;
|
||||
_app.manage(vpnservice);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.build()
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use serde::de::DeserializeOwned;
|
||||
use tauri::{
|
||||
plugin::{PluginApi, PluginHandle},
|
||||
AppHandle, Runtime,
|
||||
};
|
||||
|
||||
use crate::models::*;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
const PLUGIN_IDENTIFIER: &str = "com.plugin.vpnservice";
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
tauri::ios_plugin_binding!(init_plugin_vpnservice);
|
||||
|
||||
// initializes the Kotlin or Swift plugin classes
|
||||
pub fn init<R: Runtime, C: DeserializeOwned>(
|
||||
_app: &AppHandle<R>,
|
||||
api: PluginApi<R, C>,
|
||||
) -> crate::Result<Vpnservice<R>> {
|
||||
#[cfg(target_os = "android")]
|
||||
let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "VpnServicePlugin")?;
|
||||
#[cfg(target_os = "ios")]
|
||||
let handle = api.register_ios_plugin(init_plugin_vpnservice)?;
|
||||
Ok(Vpnservice(handle))
|
||||
}
|
||||
|
||||
/// Access to the vpnservice APIs.
|
||||
pub struct Vpnservice<R: Runtime>(PluginHandle<R>);
|
||||
|
||||
impl<R: Runtime> Vpnservice<R> {
|
||||
pub fn ping(&self, payload: PingRequest) -> crate::Result<PingResponse> {
|
||||
self.0
|
||||
.run_mobile_plugin("ping", payload)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn prepare_vpn(&self, payload: VoidRequest) -> crate::Result<Status> {
|
||||
self.0
|
||||
.run_mobile_plugin("prepare_vpn", payload)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn start_vpn(&self, payload: StartVpnRequest) -> crate::Result<Status> {
|
||||
self.0
|
||||
.run_mobile_plugin("start_vpn", payload)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn stop_vpn(&self, payload: VoidRequest) -> crate::Result<Status> {
|
||||
self.0
|
||||
.run_mobile_plugin("stop_vpn", payload)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PingRequest {
|
||||
pub value: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PingResponse {
|
||||
pub value: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VoidRequest {}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StartVpnRequest {
|
||||
pub ipv4_addr: Option<String>,
|
||||
pub routes: Option<Vec<String>>,
|
||||
pub dns: Option<String>,
|
||||
pub disallowed_applications: Option<Vec<String>>,
|
||||
pub mtu: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Status {
|
||||
pub error_msg: Option<String>,
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2021",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitAny": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["guest-js/*.ts"],
|
||||
"exclude": ["dist-js", "node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user