CH-J ToolsSSH के ज़रिए सर्वर प्रबंधन
मेनू
प्रकाशित सोर्स

CH-J Tools

किसी विशेष ऐप्लिकेशन रिलीज़ की डायरेक्टरी और फ़ाइलें देखें।

सोर्स ZIP डाउनलोड करें
CH-J / Server Manager 1704 फ़ाइलें
0.1.2-beta जोड़ा गया: · बिल्ड किया गया:
caller.rs जोड़ा गया: तारीख दर्ज नहीं 5.4 KB · 147 पंक्तियाँ
कोड फ़ाइल डाउनलोड करें
1//! Who is calling? Every command resolves the calling webview to a role before it does
2//! anything. Module windows are registered by the module runtime when it creates them;
3//! an unknown or closed window is rejected like `UNTRUSTED_PLUGIN_SENDER` in 0.1.0.
5use crate::core::error::{CoreError, CoreResult};
6use parking_lot::RwLock;
7use serde_json::Value;
8use std::collections::HashMap;
9use std::path::PathBuf;
10use std::sync::Arc;
12pub const MAIN_LABEL: &str = "main";
13pub const LICENSE_LABEL: &str = "license";
14/// Small window of a system quick action (verify/sign one file); see `core/quick.rs`.
15pub const QUICK_LABEL: &str = "quick";
16pub const MODULE_LABEL_PREFIX: &str = "module-";
18#[derive(Clone, Debug)]
19pub struct ModuleContext {
20 pub id: String,
21 pub label: String,
22 pub manifest: Value,
23 pub permissions: Vec<String>,
24 pub root: PathBuf,
27impl ModuleContext {
28 pub fn require(&self, permission: &str) -> CoreResult<()> {
29 if self.permissions.iter().any(|p| p == permission) {
30 Ok(())
31 } else {
32 Err(CoreError::new("PLUGIN_PERMISSION_DENIED", format!("Plugin permission denied: {permission}")))
33 }
34 }
37#[derive(Default)]
38pub struct WindowRegistry {
39 modules: RwLock<HashMap<String, Arc<ModuleContext>>>,
42impl WindowRegistry {
43 pub fn register_module(&self, context: ModuleContext) -> Arc<ModuleContext> {
44 let context = Arc::new(context);
45 self.modules.write().insert(context.label.clone(), context.clone());
46 context
47 }
49 pub fn unregister_module(&self, label: &str) -> Option<Arc<ModuleContext>> {
50 self.modules.write().remove(label)
51 }
53 pub fn module_by_label(&self, label: &str) -> Option<Arc<ModuleContext>> {
54 self.modules.read().get(label).cloned()
55 }
57 pub fn module_by_id(&self, id: &str) -> Option<Arc<ModuleContext>> {
58 self.modules.read().values().find(|c| c.id == id).cloned()
59 }
61 pub fn modules(&self) -> Vec<Arc<ModuleContext>> {
62 self.modules.read().values().cloned().collect()
63 }
66/// Origin checks: the main and license windows may only run the bundled app pages.
67pub fn is_app_url(url: &url::Url) -> bool {
68 match url.scheme() {
69 "tauri" => url.host_str() == Some("localhost"),
70 "http" | "https" => url.host_str() == Some("tauri.localhost"),
71 _ => false,
72 }
75pub fn require_main(label: &str, url: Option<url::Url>) -> CoreResult<()> {
76 if label == MAIN_LABEL && url.as_ref().map(is_app_url).unwrap_or(false) {
77 Ok(())
78 } else {
79 Err(CoreError::new("UNTRUSTED_IPC_SENDER", "Untrusted IPC sender."))
80 }
83pub fn require_license(label: &str, url: Option<url::Url>) -> CoreResult<()> {
84 if label == LICENSE_LABEL && url.as_ref().map(is_app_url).unwrap_or(false) {
85 Ok(())
86 } else {
87 Err(CoreError::plain("Untrusted license IPC sender."))
88 }
91pub fn require_quick(label: &str, url: Option<url::Url>) -> CoreResult<()> {
92 if label == QUICK_LABEL && url.as_ref().map(is_app_url).unwrap_or(false) {
93 Ok(())
94 } else {
95 Err(CoreError::new("UNTRUSTED_IPC_SENDER", "Untrusted IPC sender."))
96 }
99/// The page of a module window must still be the module's own entry origin.
100pub fn module_url_matches(url: &url::Url, module_id: &str) -> bool {
101 match url.scheme() {
102 "chj-module" => url.host_str() == Some(module_id),
103 "http" | "https" => {
104 url.host_str().is_some_and(|host| host.strip_prefix("chj-module.").and_then(|rest| rest.strip_suffix(".localhost")) == Some(module_id))
105 }
106 _ => false,
107 }
110pub fn require_module(registry: &WindowRegistry, label: &str, url: Option<url::Url>) -> CoreResult<Arc<ModuleContext>> {
111 let untrusted = || CoreError::new("UNTRUSTED_PLUGIN_SENDER", "Untrusted plugin IPC sender.");
112 if !label.starts_with(MODULE_LABEL_PREFIX) {
113 return Err(untrusted());
114 }
115 let context = registry.module_by_label(label).ok_or_else(untrusted)?;
116 match url {
117 Some(url) if module_url_matches(&url, &context.id) => Ok(context),
118 _ => Err(untrusted()),
119 }
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use serde_json::json;
127 #[test]
128 fn module_identity_and_permissions() {
129 let registry = WindowRegistry::default();
130 registry.register_module(ModuleContext {
131 id: "chj.users".into(),
132 label: "module-1".into(),
133 manifest: json!({}),
134 permissions: vec!["users.read".into()],
135 root: PathBuf::new(),
136 });
137 let ok = require_module(&registry, "module-1", url::Url::parse("chj-module://chj.users/ui/index.html").ok()).unwrap();
138 assert!(ok.require("users.read").is_ok());
139 assert_eq!(ok.require("users.manage").unwrap_err().code, "PLUGIN_PERMISSION_DENIED");
140 assert!(require_module(&registry, "module-1", url::Url::parse("chj-module://chj.disks/ui/index.html").ok()).is_err());
141 assert!(require_module(&registry, "module-2", url::Url::parse("chj-module://chj.users/").ok()).is_err());
142 assert!(require_module(&registry, "module-1", url::Url::parse("http://chj-module.chj.users.localhost/ui/index.html").ok()).is_ok());
143 assert!(require_main("main", url::Url::parse("tauri://localhost/index.html").ok()).is_ok());
144 assert!(require_main("main", url::Url::parse("https://evil.example/").ok()).is_err());
145 assert!(require_main("module-1", url::Url::parse("tauri://localhost/").ok()).is_err());
146 }
SHA-256e2bfa6eb4b60d48abb7aa8aa944a9db618452c0b18f5c9b96a3b639440babcff

CH-J Proprietary Software License 1.14 · सोर्स CH-J Proprietary Software License 1.14 के तहत उपलब्ध कराया जाता है। इसकी उपलब्धता लाइसेंस की शर्तें नहीं बदलती और न ही अतिरिक्त अधिकार देती है।

आर्काइव SHA-256ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f
फ़ाइलें