#!/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 # 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 # 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 # 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" # 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) || true if [[ -z "$remaining" ]]; then rm -f "$id_file" log::info "Identity '${identity_name}' removed (no remaining peers)" fi } # =========================================================================== # Peer queries # =========================================================================== # identity::peers [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 # 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 # 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" 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) || true if [[ -z "$remaining" ]]; then rm -f "$id_file" fi fi }