refactor(core): split allowlist configuration per module (#1263)

* refactor(core): split allowlist configuration per module

* fix: build with all features

* fix(cli): run fmt

* fix(core): run fmt
This commit is contained in:
Lucas Fernandes Nogueira
2021-02-20 14:09:18 -03:00
committed by GitHub
parent 75eaaf0132
commit e0be59ea26
23 changed files with 729 additions and 160 deletions

7
cli/core/Cargo.lock generated
View File

@@ -329,12 +329,6 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
[[package]]
name = "convert_case"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "core-foundation"
version = "0.9.1"
@@ -1999,7 +1993,6 @@ dependencies = [
"anyhow",
"clap 3.0.0-beta.2",
"colored",
"convert_case",
"json-patch",
"notify",
"once_cell",

View File

@@ -21,7 +21,6 @@ serde_json = "1.0"
notify = "4.0"
shared_child = "0.3"
toml_edit = "0.2"
convert_case = "0.4"
json-patch = "0.2"
schemars = "0.8"
valico = "3.5"

View File

@@ -250,6 +250,232 @@ pub struct SecurityConfig {
csp: Option<String>,
}
trait Allowlist {
fn to_features(&self) -> Vec<&str>;
}
macro_rules! check_feature {
($self:ident, $features:ident, $flag:ident, $feature_name: expr) => {
if $self.$flag {
$features.push($feature_name)
}
};
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct FsAllowlistConfig {
#[serde(default)]
all: bool,
#[serde(default)]
read_text_file: bool,
#[serde(default)]
read_binary_file: bool,
#[serde(default)]
write_file: bool,
#[serde(default)]
write_binary_file: bool,
#[serde(default)]
read_dir: bool,
#[serde(default)]
copy_file: bool,
#[serde(default)]
create_dir: bool,
#[serde(default)]
remove_dir: bool,
#[serde(default)]
remove_file: bool,
#[serde(default)]
rename_file: bool,
#[serde(default)]
path: bool,
}
impl Allowlist for FsAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["fs-all"]
} else {
let mut features = Vec::new();
check_feature!(self, features, read_text_file, "fs-read-text-file");
check_feature!(self, features, read_binary_file, "fs-read-binary-file");
check_feature!(self, features, write_file, "fs-write-file");
check_feature!(self, features, write_binary_file, "fs-write-binary-file");
check_feature!(self, features, read_dir, "fs-read-dir");
check_feature!(self, features, copy_file, "fs-copy-file");
check_feature!(self, features, create_dir, "fs-create-dir");
check_feature!(self, features, remove_dir, "fs-remove-dir");
check_feature!(self, features, remove_file, "fs-remove-file");
check_feature!(self, features, rename_file, "fs-rename-file");
check_feature!(self, features, path, "fs-path");
features
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct WindowAllowlistConfig {
#[serde(default)]
all: bool,
#[serde(default)]
create: bool,
}
impl Allowlist for WindowAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["window-all"]
} else {
let mut features = Vec::new();
check_feature!(self, features, create, "window-create");
features
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct ShellAllowlistConfig {
#[serde(default)]
all: bool,
#[serde(default)]
execute: bool,
#[serde(default)]
open: bool,
}
impl Allowlist for ShellAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["shell-all"]
} else {
let mut features = Vec::new();
check_feature!(self, features, execute, "shell-execute");
check_feature!(self, features, open, "shell-open");
features
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct DialogAllowlistConfig {
#[serde(default)]
all: bool,
#[serde(default)]
open: bool,
#[serde(default)]
save: bool,
}
impl Allowlist for DialogAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["dialog-all"]
} else {
let mut features = Vec::new();
check_feature!(self, features, open, "dialog-open");
check_feature!(self, features, save, "dialog-save");
features
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct HttpAllowlistConfig {
#[serde(default)]
all: bool,
#[serde(default)]
request: bool,
}
impl Allowlist for HttpAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["http-all"]
} else {
let mut features = Vec::new();
check_feature!(self, features, request, "http-request");
features
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct NotificationAllowlistConfig {
#[serde(default)]
all: bool,
}
impl Allowlist for NotificationAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["notification-all"]
} else {
vec![]
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct GlobalShortcutAllowlistConfig {
#[serde(default)]
all: bool,
}
impl Allowlist for GlobalShortcutAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["global-shortcut-all"]
} else {
vec![]
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct AllowlistConfig {
#[serde(default)]
all: bool,
#[serde(default)]
fs: FsAllowlistConfig,
#[serde(default)]
window: WindowAllowlistConfig,
#[serde(default)]
shell: ShellAllowlistConfig,
#[serde(default)]
dialog: DialogAllowlistConfig,
#[serde(default)]
http: HttpAllowlistConfig,
#[serde(default)]
notification: NotificationAllowlistConfig,
#[serde(default)]
global_shortcut: GlobalShortcutAllowlistConfig,
}
impl Allowlist for AllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["api-all"]
} else {
let mut features = Vec::new();
features.extend(self.fs.to_features());
features.extend(self.window.to_features());
features.extend(self.shell.to_features());
features.extend(self.dialog.to_features());
features.extend(self.http.to_features());
features.extend(self.notification.to_features());
features.extend(self.global_shortcut.to_features());
features
}
}
}
/// The Tauri configuration object.
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
@@ -265,10 +491,17 @@ pub struct TauriConfig {
#[serde(default)]
pub bundle: BundleConfig,
#[serde(default)]
pub allowlist: HashMap<String, bool>,
allowlist: AllowlistConfig,
pub security: Option<SecurityConfig>,
}
impl TauriConfig {
#[allow(dead_code)]
pub fn features(&self) -> Vec<&str> {
self.allowlist.to_features()
}
}
/// The Build configuration object.
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]

View File

@@ -31,7 +31,47 @@
"tauri": {
"description": "The Tauri configuration.",
"default": {
"allowlist": {},
"allowlist": {
"all": false,
"dialog": {
"all": false,
"open": false,
"save": false
},
"fs": {
"all": false,
"copyFile": false,
"createDir": false,
"path": false,
"readBinaryFile": false,
"readDir": false,
"readTextFile": false,
"removeDir": false,
"removeFile": false,
"renameFile": false,
"writeBinaryFile": false,
"writeFile": false
},
"globalShortcut": {
"all": false
},
"http": {
"all": false,
"request": false
},
"notification": {
"all": false
},
"shell": {
"all": false,
"execute": false,
"open": false
},
"window": {
"all": false,
"create": false
}
},
"bundle": {
"active": false,
"category": null,
@@ -76,6 +116,103 @@
},
"additionalProperties": false,
"definitions": {
"AllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
},
"dialog": {
"default": {
"all": false,
"open": false,
"save": false
},
"allOf": [
{
"$ref": "#/definitions/DialogAllowlistConfig"
}
]
},
"fs": {
"default": {
"all": false,
"copyFile": false,
"createDir": false,
"path": false,
"readBinaryFile": false,
"readDir": false,
"readTextFile": false,
"removeDir": false,
"removeFile": false,
"renameFile": false,
"writeBinaryFile": false,
"writeFile": false
},
"allOf": [
{
"$ref": "#/definitions/FsAllowlistConfig"
}
]
},
"globalShortcut": {
"default": {
"all": false
},
"allOf": [
{
"$ref": "#/definitions/GlobalShortcutAllowlistConfig"
}
]
},
"http": {
"default": {
"all": false,
"request": false
},
"allOf": [
{
"$ref": "#/definitions/HttpAllowlistConfig"
}
]
},
"notification": {
"default": {
"all": false
},
"allOf": [
{
"$ref": "#/definitions/NotificationAllowlistConfig"
}
]
},
"shell": {
"default": {
"all": false,
"execute": false,
"open": false
},
"allOf": [
{
"$ref": "#/definitions/ShellAllowlistConfig"
}
]
},
"window": {
"default": {
"all": false,
"create": false
},
"allOf": [
{
"$ref": "#/definitions/WindowAllowlistConfig"
}
]
}
},
"additionalProperties": false
},
"BuildConfig": {
"description": "The Build configuration object.",
"type": "object",
@@ -524,6 +661,24 @@
},
"additionalProperties": false
},
"DialogAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
},
"open": {
"default": false,
"type": "boolean"
},
"save": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"EmbeddedServerConfig": {
"description": "The embeddedServer configuration object.",
"type": "object",
@@ -556,6 +711,94 @@
},
"additionalProperties": false
},
"FsAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
},
"copyFile": {
"default": false,
"type": "boolean"
},
"createDir": {
"default": false,
"type": "boolean"
},
"path": {
"default": false,
"type": "boolean"
},
"readBinaryFile": {
"default": false,
"type": "boolean"
},
"readDir": {
"default": false,
"type": "boolean"
},
"readTextFile": {
"default": false,
"type": "boolean"
},
"removeDir": {
"default": false,
"type": "boolean"
},
"removeFile": {
"default": false,
"type": "boolean"
},
"renameFile": {
"default": false,
"type": "boolean"
},
"writeBinaryFile": {
"default": false,
"type": "boolean"
},
"writeFile": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"GlobalShortcutAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"HttpAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
},
"request": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"NotificationAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"OsxConfig": {
"type": "object",
"properties": {
@@ -619,16 +862,75 @@
},
"additionalProperties": false
},
"ShellAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
},
"execute": {
"default": false,
"type": "boolean"
},
"open": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"TauriConfig": {
"description": "The Tauri configuration object.",
"type": "object",
"properties": {
"allowlist": {
"default": {},
"type": "object",
"additionalProperties": {
"type": "boolean"
}
"default": {
"all": false,
"dialog": {
"all": false,
"open": false,
"save": false
},
"fs": {
"all": false,
"copyFile": false,
"createDir": false,
"path": false,
"readBinaryFile": false,
"readDir": false,
"readTextFile": false,
"removeDir": false,
"removeFile": false,
"renameFile": false,
"writeBinaryFile": false,
"writeFile": false
},
"globalShortcut": {
"all": false
},
"http": {
"all": false,
"request": false
},
"notification": {
"all": false
},
"shell": {
"all": false,
"execute": false,
"open": false
},
"window": {
"all": false,
"create": false
}
},
"allOf": [
{
"$ref": "#/definitions/AllowlistConfig"
}
]
},
"bundle": {
"description": "The bundler configuration.",
@@ -708,6 +1010,20 @@
},
"additionalProperties": false
},
"WindowAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
},
"create": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"WindowConfig": {
"description": "The window configuration object.",
"type": "object",

View File

@@ -1,6 +1,5 @@
use super::{app_paths::tauri_dir, config::ConfigHandle};
use convert_case::{Case, Casing};
use toml_edit::{Array, Document, Value};
use std::{
@@ -27,21 +26,13 @@ pub fn rewrite_manifest(config: ConfigHandle) -> crate::Result<()> {
let config = config_guard.as_ref().unwrap();
if let Some(tauri) = tauri {
let mut features: Array = Default::default();
let allowlist = &config.tauri.allowlist;
if *allowlist.get("all").unwrap_or(&false) {
features.push("all-api".to_string()).unwrap();
} else {
for (feature, enabled) in allowlist.iter() {
if *enabled {
features.push(feature.to_case(Case::Kebab)).unwrap();
}
}
let allowlist_features = config.tauri.features();
let mut features = Array::default();
for feature in allowlist_features {
features.push(feature).unwrap();
}
if config.tauri.cli.is_some() {
features.push("cli".to_string()).unwrap();
features.push("cli").unwrap();
}
match tauri {

View File

@@ -24,7 +24,7 @@ icon = [
serde_json = "1.0.62"
serde = "1.0"
serde_derive = "1.0"
tauri = { path = "../../../../../../../tauri", features =["all-api"]}
tauri = { path = "../../../../../../../tauri", features =["api-all"]}
[features]
embedded-server = [ "tauri/embedded-server" ]