最后活跃于 1 month ago

nuno 修订了这个 Gist 1 month ago. 转到此修订

1 file changed, 135 insertions

gistfile1.txt(文件已创建)

@@ -0,0 +1,135 @@
1 + function cmd::add::run() {
2 + local name=""
3 + local type=""
4 + local subtype=""
5 + local rule=""
6 + local ip=""
7 + local tunnel=""
8 + local guest=false
9 + local presets=()
10 + local show_config=false
11 + local show_qr=false
12 +
13 + # Parse flags
14 + while [[ $# -gt 0 ]]; do
15 + case "$1" in
16 + --name) name="$2"; shift 2 ;;
17 + --type) type="$2"; shift 2 ;;
18 + --subtype) subtype="$2"; shift 2 ;;
19 + --rule) rule="$2"; shift 2 ;;
20 + --ip) ip="$2"; shift 2 ;;
21 + --preset) presets+=("$2"); shift 2 ;;
22 + --guest) guest=true; shift ;;
23 + --tunnel) tunnel="$2"; shift 2 ;;
24 + --show-config) show_config=true; shift ;;
25 + --show-qr) show_qr=true; shift ;;
26 + --help) cmd::add::help; return ;;
27 + *)
28 + log::error "Unknown flag: $1"
29 + cmd::add::help
30 + return 1
31 + ;;
32 + esac
33 + done
34 +
35 + # --guest shorthand
36 + if $guest; then
37 + type="guest"
38 + fi
39 +
40 + # Resolve guest subtype
41 + local effective_type="$type"
42 + if [[ "$type" == "guest" && -n "$subtype" ]]; then
43 + # Validate subtype
44 + local valid_subtypes="desktop laptop phone tablet"
45 + if ! echo "$valid_subtypes" | grep -qw "$subtype"; then
46 + log::error "Invalid subtype: ${subtype} (valid: desktop, laptop, phone, tablet)"
47 + return 1
48 + fi
49 + effective_type="guest-${subtype}"
50 + fi
51 +
52 + # Build full client name
53 + local full_name="${type}-${name}"
54 +
55 + # Validate
56 + cmd::add::validate "$name" "$type" "$ip" "$tunnel" || return 1
57 +
58 + # Resolve tunnel mode — flag > device default
59 + if [[ -z "$tunnel" ]]; then
60 + tunnel=$(config::default_tunnel_for "$type")
61 + fi
62 +
63 + # Determine rule — explicit flag > type default
64 + if [[ -z "$rule" ]]; then
65 + if config::is_guest_type "$type"; then
66 + rule="guest"
67 + else
68 + rule="user"
69 + fi
70 + fi
71 +
72 + # Validate rule if specified
73 + if ! rule::exists "$rule"; then
74 + log::error "Rule not found: ${rule}"
75 + return 1
76 + fi
77 +
78 + local allowed_ips
79 + allowed_ips=$(config::allowed_ips_for "$effective_type" "$tunnel") || return 1
80 +
81 + log::section "Adding client: ${full_name}"
82 +
83 + # Auto-assign IP if not provided
84 + if [[ -z "$ip" ]]; then
85 + ip=$(ip::next_for_type "$effective_type") || return 1
86 + fi
87 +
88 + log::wg_add "Name: ${full_name}"
89 + log::wg_add "Type: ${type}"
90 + log::wg_add "IP: ${ip}"
91 + log::wg_add "Tunnel: ${tunnel} (${allowed_ips})"
92 +
93 + # Generate keys
94 + keys::generate_pair "$full_name" || return 1
95 +
96 + # Create client config
97 + peers::create_client_config "$full_name" "$effective_type" "$ip" "$allowed_ips" || return 1
98 +
99 + # Store subtype in meta
100 + if [[ -n "$subtype" ]]; then
101 + peers::set_meta "$full_name" "subtype" "$subtype"
102 + fi
103 +
104 + # Add peer to server config
105 + local public_key
106 + public_key=$(keys::public "$full_name") || return 1
107 + peers::add_to_server "$full_name" "$public_key" "$ip" || return 1
108 +
109 + log::wg_add "Rule: ${rule:-none}"
110 +
111 + # Apply presets
112 + for preset in "${presets[@]}"; do
113 + fw::apply_preset "$preset" "${ip}" || return 1
114 + done
115 +
116 + # Apply rule
117 + if [[ -n "$rule" ]]; then
118 + rule::apply "$rule" "$ip" || return 1
119 + fi
120 +
121 + # Reload WireGuard
122 + peers::reload || return 1
123 +
124 + log::wg_success "Client added successfully: ${full_name} (${ip}) [${tunnel} tunnel]"
125 +
126 + # Show QR for mobile by default, config for desktop/laptop
127 + local display_type="${subtype:-$type}"
128 +
129 + if cmd::add::is_mobile "$display_type"; then
130 + keys::qr "$full_name"
131 + else
132 + log::section "Client Config"
133 + cat "$(ctx::clients)/${full_name}.conf"
134 + fi
135 + }
上一页 下一页