localvault 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/localvault/cli.rb +88 -70
- data/lib/localvault/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6281a806d5f5838ea6802eaae4cb16a4276590636476151b45ed0d7ae639f1a9
|
|
4
|
+
data.tar.gz: b1aad2994aff9c31e45759672a6f2fb35f77f5f5a3fabc24b897a112997abd80
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b4b948bc2126f8ac488190d3f4d07f1ebe995d32baaf7fb458b95256507f62438d09e472cbcc059cf23d2bb91a63f05ffcd11d5585d6c0a4fec827fdc667d4cd
|
|
7
|
+
data.tar.gz: a32de3dd3fde6cba7da103d7c6d76924b236604e1cd80c28873a47dba01f52e0f99f2db7f44121a5343845e1a41a5644ff42548d96528b8c1551d0c2f47c3a10
|
data/lib/localvault/cli.rb
CHANGED
|
@@ -1073,49 +1073,53 @@ module LocalVault
|
|
|
1073
1073
|
}
|
|
1074
1074
|
end
|
|
1075
1075
|
|
|
1076
|
-
# ──
|
|
1076
|
+
# ── Render everything in tables ──
|
|
1077
1077
|
$stdout.puts
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
$stdout.puts
|
|
1082
|
-
|
|
1083
|
-
|
|
1078
|
+
|
|
1079
|
+
# OWNED BY YOU — one table with all vaults and their members
|
|
1080
|
+
unless owned.empty?
|
|
1081
|
+
$stdout.puts VAULT_STYLE.render("OWNED BY YOU")
|
|
1082
|
+
$stdout.puts render_dashboard_table(owned.sort_by { |r| r[:name] }, my_handle: my_handle)
|
|
1083
|
+
$stdout.puts
|
|
1084
1084
|
end
|
|
1085
1085
|
|
|
1086
|
-
#
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1086
|
+
# SHARED WITH YOU
|
|
1087
|
+
unless shared.empty?
|
|
1088
|
+
$stdout.puts VAULT_STYLE.render("SHARED WITH YOU")
|
|
1089
|
+
$stdout.puts render_dashboard_table(shared.sort_by { |r| r[:name] }, my_handle: my_handle)
|
|
1090
|
+
$stdout.puts
|
|
1091
|
+
end
|
|
1092
|
+
|
|
1093
|
+
if owned.empty? && shared.empty?
|
|
1094
|
+
$stdout.puts COUNT_STYLE.render("No vaults found. Create one with `localvault init NAME`.")
|
|
1095
|
+
$stdout.puts
|
|
1094
1096
|
end
|
|
1095
1097
|
|
|
1096
|
-
#
|
|
1098
|
+
# LEGACY DIRECT SHARES — only show if there are any
|
|
1097
1099
|
sent = safe_fetch_shares { client.sent_shares }
|
|
1098
1100
|
pending = safe_fetch_shares { client.pending_shares }
|
|
1099
1101
|
outgoing_count = (sent["shares"] || []).reject { |s| s["status"] == "revoked" }.size
|
|
1100
1102
|
pending_count = (pending["shares"] || []).size
|
|
1101
1103
|
|
|
1102
|
-
$stdout.puts
|
|
1103
|
-
$stdout.puts VAULT_STYLE.render("LEGACY DIRECT SHARES") + " " + COUNT_STYLE.render("(pre-v1.2 fallback)")
|
|
1104
|
-
$stdout.puts " outgoing: #{outgoing_count} pending: #{pending_count}"
|
|
1105
1104
|
if outgoing_count + pending_count > 0
|
|
1106
|
-
$stdout.puts
|
|
1105
|
+
$stdout.puts VAULT_STYLE.render("LEGACY DIRECT SHARES")
|
|
1106
|
+
legacy_rows = []
|
|
1107
|
+
(sent["shares"] || []).reject { |s| s["status"] == "revoked" }.each do |s|
|
|
1108
|
+
legacy_rows << [s["vault_name"] || "—", "@#{s["recipient_handle"]}", s["status"], "outgoing"]
|
|
1109
|
+
end
|
|
1110
|
+
(pending["shares"] || []).each do |s|
|
|
1111
|
+
legacy_rows << [s["vault_name"] || "—", "@#{s["sender_handle"]}", "pending", "incoming"]
|
|
1112
|
+
end
|
|
1113
|
+
$stdout.puts render_legacy_shares_table(legacy_rows)
|
|
1114
|
+
$stdout.puts
|
|
1107
1115
|
end
|
|
1108
1116
|
|
|
1109
|
-
#
|
|
1117
|
+
# Skipped
|
|
1110
1118
|
unless skipped.empty?
|
|
1119
|
+
$stderr.puts COUNT_STYLE.render("#{skipped.size} vault(s) could not be loaded:")
|
|
1120
|
+
skipped.each { |name, reason| $stderr.puts " #{name}: #{reason}" }
|
|
1111
1121
|
$stdout.puts
|
|
1112
|
-
$stderr.puts "Note: #{skipped.size} vault(s) could not be loaded:"
|
|
1113
|
-
skipped.each do |name, reason|
|
|
1114
|
-
$stderr.puts " #{name}: #{reason}"
|
|
1115
|
-
end
|
|
1116
1122
|
end
|
|
1117
|
-
|
|
1118
|
-
$stdout.puts
|
|
1119
1123
|
end
|
|
1120
1124
|
|
|
1121
1125
|
desc "import FILE", "Bulk-import secrets from a .env, .json, or .yml file"
|
|
@@ -1408,53 +1412,70 @@ module LocalVault
|
|
|
1408
1412
|
end
|
|
1409
1413
|
end
|
|
1410
1414
|
|
|
1411
|
-
# Render
|
|
1412
|
-
#
|
|
1413
|
-
#
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
count_label = "#{valid.size} member#{valid.size == 1 ? "" : "s"}"
|
|
1419
|
-
owner_label = row[:owner] ? "owner @#{row[:owner]}" : "personal"
|
|
1420
|
-
|
|
1421
|
-
# Sync status badge
|
|
1422
|
-
sync_badge = case row[:sync_status]
|
|
1423
|
-
when "synced" then "synced #{row[:synced_at]}"
|
|
1424
|
-
when "remote only" then "remote only"
|
|
1425
|
-
when "local only" then "local only — not synced"
|
|
1426
|
-
else row[:sync_status] || "unknown"
|
|
1427
|
-
end
|
|
1428
|
-
sync_badge += " · #{row[:size_label]}" if row[:size_label]
|
|
1429
|
-
|
|
1430
|
-
$stdout.puts " " + GROUP_STYLE.render(row[:name]) + " " +
|
|
1431
|
-
COUNT_STYLE.render("#{count_label} · #{owner_label} · #{sync_badge}")
|
|
1432
|
-
|
|
1433
|
-
if !row[:is_team]
|
|
1434
|
-
$stdout.puts " " + COUNT_STYLE.render("No team members. Convert with `localvault team init #{row[:name]}` to share.")
|
|
1435
|
-
$stdout.puts
|
|
1436
|
-
return
|
|
1437
|
-
end
|
|
1415
|
+
# Render a single Lipgloss table for all vaults in a section (owned / shared).
|
|
1416
|
+
# Each vault contributes rows: the vault itself as a summary row, then one
|
|
1417
|
+
# row per team member. Personal vaults get a single summary row.
|
|
1418
|
+
#
|
|
1419
|
+
# Columns: Vault | Member | Access | Scopes | Sync | Size
|
|
1420
|
+
def render_dashboard_table(vault_rows, my_handle:)
|
|
1421
|
+
require "lipgloss"
|
|
1438
1422
|
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1423
|
+
rows = []
|
|
1424
|
+
vault_rows.each_with_index do |vr, idx|
|
|
1425
|
+
slots = vr[:key_slots]
|
|
1426
|
+
valid = slots.select { |_, v| v.is_a?(Hash) && v["pub"].is_a?(String) }
|
|
1427
|
+
|
|
1428
|
+
sync_label = case vr[:sync_status]
|
|
1429
|
+
when "synced" then "synced #{vr[:synced_at]}"
|
|
1430
|
+
when "remote only" then "remote only"
|
|
1431
|
+
when "local only" then "local only"
|
|
1432
|
+
else vr[:sync_status] || "—"
|
|
1433
|
+
end
|
|
1434
|
+
size_col = vr[:size_label] || "—"
|
|
1435
|
+
owner_col = vr[:owner] ? "@#{vr[:owner]}" : "personal"
|
|
1436
|
+
|
|
1437
|
+
if valid.empty?
|
|
1438
|
+
# Single summary row for personal / empty team vaults
|
|
1439
|
+
rows << [vr[:name], owner_col, "—", "—", sync_label, size_col]
|
|
1440
|
+
else
|
|
1441
|
+
# First member row carries the vault name; subsequent rows leave it blank
|
|
1442
|
+
valid.sort.each_with_index do |(handle, slot), mi|
|
|
1443
|
+
vault_col = mi == 0 ? vr[:name] : ""
|
|
1444
|
+
owner_show = mi == 0 ? owner_col : ""
|
|
1445
|
+
sync_show = mi == 0 ? sync_label : ""
|
|
1446
|
+
size_show = mi == 0 ? size_col : ""
|
|
1447
|
+
|
|
1448
|
+
marker = handle == my_handle ? " (you)" : ""
|
|
1449
|
+
access = slot["scopes"].is_a?(Array) ? "scoped" : "full"
|
|
1450
|
+
scopes = slot["scopes"].is_a?(Array) ? slot["scopes"].join(", ") : "—"
|
|
1451
|
+
|
|
1452
|
+
rows << [vault_col, "@#{handle}#{marker}", access, scopes, sync_show, size_show]
|
|
1453
|
+
end
|
|
1454
|
+
end
|
|
1443
1455
|
end
|
|
1444
1456
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1457
|
+
Lipgloss::Table.new
|
|
1458
|
+
.headers(["Vault", "Member", "Access", "Scopes", "Sync", "Size"])
|
|
1459
|
+
.rows(rows)
|
|
1460
|
+
.border(:rounded)
|
|
1461
|
+
.style_func(rows: rows.size, columns: 6) do |row_idx, _col|
|
|
1462
|
+
if row_idx == Lipgloss::Table::HEADER_ROW
|
|
1463
|
+
HEADER_STYLE
|
|
1464
|
+
else
|
|
1465
|
+
row_idx.odd? ? ODD_STYLE : EVEN_STYLE
|
|
1466
|
+
end
|
|
1467
|
+
end
|
|
1468
|
+
.render
|
|
1469
|
+
end
|
|
1451
1470
|
|
|
1471
|
+
# Render legacy direct shares as a single table.
|
|
1472
|
+
def render_legacy_shares_table(rows)
|
|
1452
1473
|
require "lipgloss"
|
|
1453
|
-
|
|
1454
|
-
.headers(["
|
|
1474
|
+
Lipgloss::Table.new
|
|
1475
|
+
.headers(["Vault", "User", "Status", "Direction"])
|
|
1455
1476
|
.rows(rows)
|
|
1456
1477
|
.border(:rounded)
|
|
1457
|
-
.style_func(rows: rows.size, columns:
|
|
1478
|
+
.style_func(rows: rows.size, columns: 4) do |row_idx, _col|
|
|
1458
1479
|
if row_idx == Lipgloss::Table::HEADER_ROW
|
|
1459
1480
|
HEADER_STYLE
|
|
1460
1481
|
else
|
|
@@ -1462,9 +1483,6 @@ module LocalVault
|
|
|
1462
1483
|
end
|
|
1463
1484
|
end
|
|
1464
1485
|
.render
|
|
1465
|
-
|
|
1466
|
-
$stdout.puts table
|
|
1467
|
-
$stdout.puts
|
|
1468
1486
|
end
|
|
1469
1487
|
|
|
1470
1488
|
# Fetch shares, swallowing API errors so the dashboard never bails
|
data/lib/localvault/version.rb
CHANGED