212 lines
No EOL
7.2 KiB
Bash
212 lines
No EOL
7.2 KiB
Bash
#!/usr/bin/env bash
|
|
# identity.module.sh — identity file management and peer-name inference
|
|
|
|
# ===========================================================================
|
|
# Path helpers
|
|
# ===========================================================================
|
|
|
|
function identity::path() {
|
|
local name="${1:-}"
|
|
echo "$(ctx::identities)/${name}.identity"
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Existence checks
|
|
# ===========================================================================
|
|
|
|
function identity::exists() {
|
|
local name="${1:-}"
|
|
json::identity_exists "$(identity::path "$name")" 2>/dev/null
|
|
}
|
|
|
|
function identity::require_exists() {
|
|
local name="${1:-}"
|
|
if ! identity::exists "$name"; then
|
|
log::error "Identity '${name}' not found. Use 'wgctl identity list' to see all identities."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function identity::require_not_exists() {
|
|
local name="${1:-}"
|
|
if identity::exists "$name"; then
|
|
log::error "Identity '${name}' already exists."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Peer name inference
|
|
# ===========================================================================
|
|
|
|
# identity::infer <peer_name>
|
|
# Parses a peer name and returns "identity_name|type|index" if it matches
|
|
# the naming convention, or empty string if not.
|
|
# phone-nuno -> "nuno|phone|1"
|
|
# phone-nuno-2 -> "nuno|phone|2"
|
|
# roboclean -> "" (no type prefix)
|
|
function identity::infer() {
|
|
local peer_name="${1:-}"
|
|
json::identity_infer "$peer_name" 2>/dev/null || true
|
|
}
|
|
|
|
# identity::next_index <identity_name> <type>
|
|
# Returns the next available device index for a type within an identity.
|
|
# If identity doesn't exist yet, returns 1.
|
|
function identity::next_index() {
|
|
local identity_name="${1:-}" peer_type="${2:-}"
|
|
local id_file
|
|
id_file=$(identity::path "$identity_name")
|
|
if [[ ! -f "$id_file" ]]; then
|
|
echo 1
|
|
return 0
|
|
fi
|
|
json::identity_next_index "$id_file" "$peer_type" 2>/dev/null || echo 1
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Auto-attach (called from wgctl add)
|
|
# ===========================================================================
|
|
|
|
# identity::auto_attach <peer_name> <peer_type>
|
|
# Infers identity from peer name and adds the peer to the identity file.
|
|
# Creates the identity file if it doesn't exist.
|
|
# Silent — no output. Logs a note on success, silently skips if no match.
|
|
function identity::auto_attach() {
|
|
local peer_name="${1:-}" peer_type="${2:-}"
|
|
local inferred
|
|
inferred=$(identity::infer "$peer_name")
|
|
[[ -z "$inferred" ]] && return 0
|
|
|
|
local identity_name type_inferred index
|
|
identity_name=$(echo "$inferred" | cut -d'|' -f1)
|
|
type_inferred=$(echo "$inferred" | cut -d'|' -f2)
|
|
index=$(echo "$inferred" | cut -d'|' -f3)
|
|
|
|
# Use the explicit type if provided, otherwise use inferred type
|
|
local final_type="${peer_type:-$type_inferred}"
|
|
|
|
local id_file
|
|
id_file=$(identity::path "$identity_name")
|
|
|
|
json::identity_add_peer "$id_file" "$identity_name" "$peer_name" "$final_type" "$index" </dev/null
|
|
log::info "Attached '${peer_name}' to identity '${identity_name}' (${final_type} #${index})"
|
|
}
|
|
|
|
# identity::auto_detach <peer_name>
|
|
# Removes a peer from its identity file when the peer is deleted.
|
|
# If the identity has no remaining peers, removes the identity file too.
|
|
function identity::auto_detach() {
|
|
local peer_name="${1:-}"
|
|
local inferred
|
|
inferred=$(identity::infer "$peer_name")
|
|
[[ -z "$inferred" ]] && return 0
|
|
|
|
local identity_name
|
|
identity_name=$(echo "$inferred" | cut -d'|' -f1)
|
|
local id_file
|
|
id_file=$(identity::path "$identity_name")
|
|
[[ ! -f "$id_file" ]] && return 0
|
|
|
|
json::identity_remove_peer "$id_file" "$peer_name" </dev/null
|
|
|
|
# Remove identity file if now empty
|
|
local remaining
|
|
remaining=$(json::identity_peers "$id_file" 2>/dev/null) || true
|
|
if [[ -z "$remaining" ]]; then
|
|
rm -f "$id_file"
|
|
log::info "Identity '${identity_name}' removed (no remaining peers)"
|
|
fi
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Peer queries
|
|
# ===========================================================================
|
|
|
|
# identity::peers <identity_name> [type_filter]
|
|
# Returns peer names belonging to an identity, one per line.
|
|
# Optional type_filter limits to peers of a specific type.
|
|
function identity::peers() {
|
|
local identity_name="${1:-}" type_filter="${2:-}"
|
|
local id_file
|
|
id_file=$(identity::path "$identity_name")
|
|
json::identity_peers "$id_file" "$type_filter" 2>/dev/null || true
|
|
}
|
|
|
|
# identity::get_name <peer_name>
|
|
# Returns the identity name for a given peer (via inference).
|
|
function identity::get_name() {
|
|
local peer_name="${1:-}"
|
|
local inferred
|
|
inferred=$(identity::infer "$peer_name")
|
|
[[ -n "$inferred" ]] && echo "${inferred%%|*}"
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Data for commands
|
|
# ===========================================================================
|
|
|
|
function identity::list_data() {
|
|
json::identity_list "$(ctx::identities)" 2>/dev/null || true
|
|
}
|
|
|
|
function identity::show_data() {
|
|
local name="${1:-}"
|
|
json::identity_show "$(identity::path "$name")" 2>/dev/null
|
|
}
|
|
|
|
# ===========================================================================
|
|
# Rename helper (called from rename.command.sh)
|
|
# ===========================================================================
|
|
|
|
# identity::rename_peer <old_peer_name> <new_peer_name>
|
|
# Updates identity file entry when a peer is renamed.
|
|
# Re-infers identity from old name, removes old entry, adds new entry.
|
|
function identity::rename_peer() {
|
|
local old_name="${1:-}" new_name="${2:-}"
|
|
|
|
local old_inferred
|
|
old_inferred=$(identity::infer "$old_name")
|
|
[[ -z "$old_inferred" ]] && return 0
|
|
|
|
local identity_name old_type old_index
|
|
identity_name=$(echo "$old_inferred" | cut -d'|' -f1)
|
|
old_type=$(echo "$old_inferred" | cut -d'|' -f2)
|
|
old_index=$(echo "$old_inferred" | cut -d'|' -f3)
|
|
|
|
local id_file
|
|
id_file=$(identity::path "$identity_name")
|
|
[[ ! -f "$id_file" ]] && return 0
|
|
|
|
# Infer new identity context from new name
|
|
local new_inferred new_identity new_type new_index
|
|
new_inferred=$(identity::infer "$new_name")
|
|
if [[ -n "$new_inferred" ]]; then
|
|
new_identity=$(echo "$new_inferred" | cut -d'|' -f1)
|
|
new_type=$(echo "$new_inferred" | cut -d'|' -f2)
|
|
new_index=$(echo "$new_inferred" | cut -d'|' -f3)
|
|
else
|
|
# New name doesn't match convention — detach cleanly
|
|
json::identity_remove_peer "$id_file" "$old_name" </dev/null
|
|
return 0
|
|
fi
|
|
|
|
# Remove old entry
|
|
json::identity_remove_peer "$id_file" "$old_name" </dev/null
|
|
|
|
if [[ "$new_identity" == "$identity_name" ]]; then
|
|
# Same identity — update in place
|
|
json::identity_add_peer "$id_file" "$identity_name" "$new_name" "$new_type" "$new_index" </dev/null
|
|
else
|
|
# Identity changed (e.g. phone-nuno -> phone-helena) — move to new identity file
|
|
local new_id_file
|
|
new_id_file=$(identity::path "$new_identity")
|
|
json::identity_add_peer "$new_id_file" "$new_identity" "$new_name" "$new_type" "$new_index" </dev/null
|
|
# Clean up old identity if empty
|
|
local remaining
|
|
remaining=$(json::identity_peers "$id_file" 2>/dev/null) || true
|
|
if [[ -z "$remaining" ]]; then
|
|
rm -f "$id_file"
|
|
fi
|
|
fi
|
|
} |