CH-J ToolsSSH-এর মাধ্যমে সার্ভার ব্যবস্থাপনা
মেনু
প্রকাশিত সোর্স

CH-J Tools

নির্দিষ্ট একটি অ্যাপ্লিকেশন রিলিজের ডিরেক্টরি ও ফাইল ব্রাউজ করুন।

সোর্স ZIP ডাউনলোড করুন
CH-J / Server Manager 1704 টি ফাইল
0.1.2-beta যোগ করা হয়েছে: · বিল্ড হয়েছে:
matrix.rs যোগ করা হয়েছে: তারিখ নথিভুক্ত নেই ৭.২ KB · 158 লাইন
কোড ফাইল ডাউনলোড করুন
1//! Matrix API: the only source of remote commands. Core services name an operation; the matrix, compiled
2//! into the binary from `Matrix json`, decides whether it exists on the server's OS and which fixed script
3//! and leading arguments run. Nothing here accepts commands or scripts from the UI or from files at run time.
5use crate::core::error::{CoreError, CoreResult};
6use crate::core::ssh::session::shell_quote;
7use once_cell::sync::Lazy;
8use serde::Deserialize;
9use serde_json::Value;
10use std::collections::HashMap;
12#[derive(Deserialize)]
13struct Runtime {
14 script: Option<String>,
15 #[serde(default)]
16 argv: Vec<String>,
17 key: Option<String>,
20#[derive(Deserialize)]
21struct Catalog {
22 operations: HashMap<String, HashMap<String, Runtime>>,
23 available: HashMap<String, Vec<String>>,
24 scripts: HashMap<String, String>,
27static CATALOG: Lazy<Catalog> = Lazy::new(|| serde_json::from_str(include_str!(concat!(env!("OUT_DIR"), "/matrix-runtime.json"))).expect("matrix runtime"));
29/// Scripts are generic for a family, so an unrecognised POSIX system behaves like its nearest relative.
30const FALLBACK_OS: &str = "debian";
32#[derive(Debug)]
33pub struct Binding {
34 pub script: &'static str,
35 pub argv: &'static [String],
38/// The matrix OS of a detected platform.
39pub fn os_of(platform: &Value) -> &str {
40 if platform["os"] == "windows" {
41 return "windows";
42 }
43 platform["matrixOs"].as_str().unwrap_or(FALLBACK_OS)
46fn unsupported(operation: &str, os: &str) -> CoreError {
47 CoreError::new("FEATURE_PLATFORM_UNSUPPORTED", format!("This operation is not available on this server's operating system ({os}).")).with("operation", Value::from(operation))
50pub fn binding(operation: &str, os: &str) -> CoreResult<Binding> {
51 let runtime = CATALOG.operations.get(operation).and_then(|systems| systems.get(os)).filter(|runtime| runtime.script.is_some()).ok_or_else(|| unsupported(operation, os))?;
52 Ok(Binding { script: script(runtime.script.as_deref().expect("filtered")), argv: &runtime.argv })
55/// Fails on a system where the matrix does not offer the operation, also for operations that run no script (SFTP).
56pub fn require(operation: &str, os: &str) -> CoreResult<()> {
57 if CATALOG.available.get(operation).is_some_and(|systems| systems.iter().any(|system| system == os)) {
58 Ok(())
59 } else {
60 Err(unsupported(operation, os))
61 }
64/// A script by file name. Names come from Core constants and the build rejects a missing file.
65pub fn script(name: &str) -> &'static str {
66 CATALOG.scripts.get(name).map(String::as_str).unwrap_or_else(|| panic!("matrix script {name}"))
69/// The operation behind a dynamic action (`users:manage action=...`) of one script.
70pub fn operation_by_key(script_name: &str, key: &str, os: &str) -> Option<&'static str> {
71 CATALOG.operations.iter().find_map(|(id, systems)| {
72 let runtime = systems.get(os)?;
73 (runtime.key.as_deref() == Some(key) && runtime.script.as_deref() == Some(script_name)).then_some(id.as_str())
74 })
77/// A script as a command for a server whose login shell may not be POSIX.
78pub fn shell(script_text: &str) -> String {
79 format!("sh -c {}", shell_quote(script_text))
82/// The command line of a script. Arguments are quoted and never become part of the script text.
83pub fn command(script_text: &str, args: &[String]) -> String {
84 if args.is_empty() {
85 return script_text.to_string();
86 }
87 format!("sh -c {} chj {}", shell_quote(script_text), args.iter().map(|arg| shell_quote(arg)).collect::<Vec<_>>().join(" "))
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use serde_json::json;
95 const OSES: [&str; 7] = ["ubuntu", "debian", "arch", "rocky", "alpine", "windows", "openwrt"];
97 #[test]
98 fn every_binding_names_a_compiled_script() {
99 let mut bound = 0;
100 for (id, systems) in &CATALOG.operations {
101 for os in systems.keys() {
102 assert!(OSES.contains(&os.as_str()), "{id}/{os}");
103 if systems[os].script.is_some() {
104 assert!(!binding(id, os).unwrap().script.is_empty(), "{id}/{os}");
105 bound += 1;
106 }
107 }
108 }
109 assert!(bound > 400, "{bound}");
110 }
112 #[test]
113 fn operations_named_by_core_exist() {
114 for id in ["users.inventory", "users.detail", "users.create", "users.keys.add", "users.keys.remove", "users.ssh-policy.apply", "disk.inventory.read", "disk.health.read", "disk.job.start", "disk.job.read", "disk.jobs.list", "system.swap.configuration.read", "system.os.read", "nginx.inspect", "nginx.config.read", "nginx.config.dump", "nginx.config.test", "nginx.config.save", "nginx.reload", "editor.read", "files.checksum.read", "terminal.suggestions.read", "privilege.probe", "ssh.platform.detect"] {
115 assert!(binding(id, "ubuntu").is_ok(), "{id}");
116 }
117 for id in ["users.privileges", "users.inventory", "users.detail", "users.create", "users.delete", "users.keys.add", "users.keys.remove", "users.ssh-policy.apply", "system.pagefile.read", "system.pagefile.set", "system.pagefile.automatic", "system.pagefile.remove", "system.os.read", "hash.remote.calculate", "ssh.platform.detect"] {
118 assert!(binding(id, "windows").is_ok(), "{id}");
119 }
120 for action in ["create", "activate", "deactivate", "priority", "persist", "resize", "delete"] {
121 assert_eq!(binding(&format!("system.swap.{action}"), "rocky").unwrap().argv, ["manage", action]);
122 }
123 }
125 #[test]
126 fn dynamic_actions_reach_one_operation() {
127 for key in ["lock", "unlock", "expire", "unexpire", "password", "shell", "comment", "home", "primary", "group-add", "group-remove", "sudo-grant", "sudo-revoke", "delete"] {
128 assert!(operation_by_key("remoteUsers.sh", key, "alpine").is_some(), "{key}");
129 }
130 for key in ["enable", "disable", "password", "fullName", "description", "group-add", "group-remove", "admin-grant", "admin-revoke"] {
131 assert!(operation_by_key("windows/remoteUsers.ps1", key, "windows").is_some(), "{key}");
132 }
133 assert_eq!(binding("users.groups.add", "debian").unwrap().argv, ["account", "group-add"]);
134 assert_eq!(binding("users.groups.add", "windows").unwrap().argv, ["account", "group-add"]);
135 }
137 #[test]
138 fn openwrt_has_only_the_terminal() {
139 assert_eq!(binding("users.inventory", "openwrt").unwrap_err().code, "FEATURE_PLATFORM_UNSUPPORTED");
140 assert_eq!(binding("system.os.read", "openwrt").unwrap_err().code, "FEATURE_PLATFORM_UNSUPPORTED");
141 assert_eq!(require("files.channel.open", "openwrt").unwrap_err().code, "FEATURE_PLATFORM_UNSUPPORTED");
142 assert!(binding("terminal.suggestions.read", "openwrt").is_ok());
143 assert!(require("files.channel.open", "ubuntu").is_ok());
144 }
146 #[test]
147 fn platform_selects_the_matrix() {
148 assert_eq!(os_of(&json!({ "os": "windows" })), "windows");
149 assert_eq!(os_of(&json!({ "os": "linux", "matrixOs": "rocky" })), "rocky");
150 assert_eq!(os_of(&json!({ "os": "posix" })), "debian");
151 }
153 #[test]
154 fn arguments_stay_outside_the_script() {
155 assert_eq!(command("exit 0\n", &[]), "exit 0\n");
156 assert_eq!(command("echo \"$1\"", &["a b; rm".into()]), "sh -c 'echo \"$1\"' chj 'a b; rm'");
157 }
SHA-25679404cdfdd4754c09c113280dcb4a2575d1d0c812e587654671cd7e7a3af6738

CH-J Proprietary Software License 1.14 · সোর্স CH-J Proprietary Software License 1.14-এর অধীনে দেওয়া হয়। এর প্রাপ্যতা লাইসেন্সের শর্ত বদলায় না এবং অতিরিক্ত কোনো অধিকারও দেয় না।

আর্কাইভ SHA-256ac8fe790f4ba60fc098f8c985fc2656cfcc6cdc21fb34b30e308a2b54e62258f
ফাইল