-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(cli): add new acl subcommands (#8827)
* unify `CI` var handling, and lay foundation for `permission` subcommand * feat(cli/init&new): create `permissions` directory by default for plugins * generate permissions with consistent pathing on windows and unix * `pemrission create` initial implementation * add ls command * finalize `permission create` subcommand * `permission rm` subcommand * `permission add` subcommand * remove empty `permission copy` subcommand * clippy * `capability create` subcommand and move modules under `acl` directory * fix multiselect for `permission add` when capabilty doesn't have identifier * clippy * `create` -> `new` and change file * license headers * more license headers * clippy * Discard changes to examples/resources/src-tauri/.gitignore * fix build * cleanup --------- Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
- Loading branch information
1 parent
9be314f
commit 06d63d6
Showing
30 changed files
with
949 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
'tauri-cli': 'patch:feat' | ||
'@tauri-apps/cli': 'patch:feat' | ||
--- | ||
|
||
Add new subcommands for managing permissions and cababilities: | ||
|
||
- `tauri permission new` | ||
- `tauri permission add` | ||
- `tauri permission rm` | ||
- `tauri permission ls` | ||
- `tauri capability new` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// SPDX-License-Identifier: MIT | ||
|
||
use clap::{Parser, Subcommand}; | ||
|
||
use crate::Result; | ||
|
||
mod new; | ||
|
||
#[derive(Debug, Parser)] | ||
#[clap(about = "Manage or create capabilities for your app")] | ||
pub struct Cli { | ||
#[clap(subcommand)] | ||
command: Commands, | ||
} | ||
|
||
#[derive(Subcommand, Debug)] | ||
enum Commands { | ||
#[clap(alias = "create")] | ||
New(new::Options), | ||
} | ||
|
||
pub fn command(cli: Cli) -> Result<()> { | ||
match cli.command { | ||
Commands::New(options) => new::command(options), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// SPDX-License-Identifier: MIT | ||
|
||
use std::{collections::HashSet, path::PathBuf}; | ||
|
||
use clap::Parser; | ||
use tauri_utils::acl::capability::{Capability, PermissionEntry}; | ||
|
||
use crate::{ | ||
acl::FileFormat, | ||
helpers::{app_paths::tauri_dir, prompts}, | ||
Result, | ||
}; | ||
|
||
#[derive(Debug, Parser)] | ||
#[clap(about = "Create a new permission file")] | ||
pub struct Options { | ||
/// Capability identifier. | ||
identifier: Option<String>, | ||
/// Capability description | ||
#[clap(long)] | ||
description: Option<String>, | ||
/// Capability windows | ||
#[clap(long)] | ||
windows: Option<Vec<String>>, | ||
/// Capability permissions | ||
#[clap(long)] | ||
permission: Option<Vec<String>>, | ||
/// Output file format. | ||
#[clap(long, default_value_t = FileFormat::Json)] | ||
format: FileFormat, | ||
/// The output file. | ||
#[clap(short, long)] | ||
out: Option<PathBuf>, | ||
} | ||
|
||
pub fn command(options: Options) -> Result<()> { | ||
let identifier = match options.identifier { | ||
Some(i) => i, | ||
None => prompts::input("What's the capability identifier?", None, false, false)?.unwrap(), | ||
}; | ||
|
||
let description = match options.description { | ||
Some(d) => Some(d), | ||
None => prompts::input::<String>("What's the capability description?", None, false, true)? | ||
.and_then(|d| if d.is_empty() { None } else { Some(d) }), | ||
}; | ||
|
||
let windows = match options.windows.map(FromIterator::from_iter) { | ||
Some(w) => w, | ||
None => prompts::input::<String>( | ||
"Which windows should be affected by this? (comma separated)", | ||
Some("main".into()), | ||
false, | ||
false, | ||
)? | ||
.and_then(|d| { | ||
if d.is_empty() { | ||
None | ||
} else { | ||
Some(d.split(',').map(ToString::to_string).collect()) | ||
} | ||
}) | ||
.unwrap_or_default(), | ||
}; | ||
|
||
let permissions: HashSet<String> = match options.permission.map(FromIterator::from_iter) { | ||
Some(p) => p, | ||
None => prompts::input::<String>( | ||
"What permissions to enable? (comma separated)", | ||
None, | ||
false, | ||
true, | ||
)? | ||
.and_then(|p| { | ||
if p.is_empty() { | ||
None | ||
} else { | ||
Some(p.split(',').map(ToString::to_string).collect()) | ||
} | ||
}) | ||
.unwrap_or_default(), | ||
}; | ||
|
||
let capability = Capability { | ||
identifier, | ||
description: description.unwrap_or_default(), | ||
remote: None, | ||
local: true, | ||
windows, | ||
webviews: Vec::new(), | ||
permissions: permissions | ||
.into_iter() | ||
.map(|p| { | ||
PermissionEntry::PermissionRef( | ||
p.clone() | ||
.try_into() | ||
.unwrap_or_else(|_| panic!("invalid permission {}", p)), | ||
) | ||
}) | ||
.collect(), | ||
platforms: Vec::new(), | ||
}; | ||
|
||
let path = match options.out { | ||
Some(o) => o.canonicalize()?, | ||
None => { | ||
let dir = tauri_dir(); | ||
let capabilities_dir = dir.join("capabilities"); | ||
capabilities_dir.join(format!( | ||
"{}.{}", | ||
capability.identifier, | ||
options.format.extension() | ||
)) | ||
} | ||
}; | ||
|
||
if path.exists() { | ||
let msg = format!( | ||
"Capability already exists at {}", | ||
dunce::simplified(&path).display() | ||
); | ||
let overwrite = prompts::confirm(&format!("{msg}, overwrite?"), Some(false))?; | ||
if overwrite { | ||
std::fs::remove_file(&path)?; | ||
} else { | ||
anyhow::bail!(msg); | ||
} | ||
} | ||
|
||
if let Some(parent) = path.parent() { | ||
std::fs::create_dir_all(parent)?; | ||
} | ||
|
||
std::fs::write(&path, options.format.serialize(&capability)?)?; | ||
|
||
log::info!(action = "Created"; "capability at {}", dunce::simplified(&path).display()); | ||
|
||
Ok(()) | ||
} |
Oops, something went wrong.