Module: Browserctl::Commands::State

Extended by:
CliOutput
Defined in:
lib/browserctl/commands/state.rb

Overview

‘browserctl state` — top-level command for portable, encrypted, origin- scoped browser state. Wraps the daemon’s state_* RPCs.

Constant Summary collapse

USAGE =
"Usage: browserctl state <save|load|list|info|delete|rotate|export|import> [args]"
DAEMON_SUBCOMMANDS =
{
  "save" => :run_save, "load" => :run_load, "list" => :run_list,
  "info" => :run_info, "delete" => :run_delete, "rotate" => :run_rotate
}.freeze
LOCAL_SUBCOMMANDS =
{ "export" => :run_export, "import" => :run_import }.freeze

Constants included from CliOutput

CliOutput::AUTH_REQUIRED_EXIT_CODE

Class Method Summary collapse

Methods included from CliOutput

exit_code_for, print_result, structured_error_line

Class Method Details

.run(client, args) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/browserctl/commands/state.rb', line 23

def self.run(client, args)
  sub = args.shift or abort USAGE

  if (m = DAEMON_SUBCOMMANDS[sub])
    sub == "list" ? send(m, client) : send(m, client, args)
  elsif (m = LOCAL_SUBCOMMANDS[sub])
    send(m, args)
  else
    abort "unknown state subcommand '#{sub}'\n#{USAGE}"
  end
end

.run_delete(client, args) ⇒ Object



69
70
71
72
# File 'lib/browserctl/commands/state.rb', line 69

def self.run_delete(client, args)
  name = args.shift or abort "usage: browserctl state delete <name>"
  print_result(client.state_delete(name))
end

.run_export(args) ⇒ Object



129
130
131
132
133
134
135
136
137
138
# File 'lib/browserctl/commands/state.rb', line 129

def self.run_export(args)
  name        = args.shift or abort "usage: browserctl state export <name> <destination>"
  destination = args.shift or abort "usage: browserctl state export <name> <destination>"
  require "browserctl/state"
  result = Browserctl::State.export(name, destination)
  puts result.to_json
rescue Browserctl::State::Transport::TransportError, Browserctl::Error, ArgumentError => e
  warn "Error: #{e.message}"
  exit 1
end

.run_import(args) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/browserctl/commands/state.rb', line 140

def self.run_import(args)
  name_override = extract_value!(args, "--name")
  source        = args.shift or abort "usage: browserctl state import <source> [--name NAME]"
  require "browserctl/state"
  result = Browserctl::State.import(source, name: name_override)
  puts result.to_json
rescue Browserctl::State::Transport::TransportError,
       Browserctl::State::Bundle::BundleError,
       Browserctl::Error, ArgumentError => e
  warn "Error: #{e.message}"
  exit 1
end

.run_info(client, args) ⇒ Object



64
65
66
67
# File 'lib/browserctl/commands/state.rb', line 64

def self.run_info(client, args)
  name = args.shift or abort "usage: browserctl state info <name>"
  print_result(client.state_info(name))
end

.run_list(client) ⇒ Object



60
61
62
# File 'lib/browserctl/commands/state.rb', line 60

def self.run_list(client)
  print_result(client.state_list)
end

.run_load(client, args) ⇒ Object



54
55
56
57
58
# File 'lib/browserctl/commands/state.rb', line 54

def self.run_load(client, args)
  name = args.shift or abort "usage: browserctl state load <name>"
  passphrase = state_needs_passphrase?(client, name) ? prompt_passphrase : nil
  print_result(client.state_load(name, passphrase: passphrase))
end

.run_rotate(client, args) ⇒ Object

Re-runs the flow bound to <name> and re-saves the bundle. The flow is read from the manifest (set when the bundle was originally produced via ‘state save –flow …`). Params come from –params or k=v pairs.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/browserctl/commands/state.rb', line 77

def self.run_rotate(client, args)
  require "browserctl/flow_registry"
  page_name   = extract_value!(args, "--page")
  params_path = extract_value!(args, "--params")
  name        = args.shift or abort "usage: browserctl state rotate <name> " \
                                    "[--page NAME] [--params FILE] [--key value ...]"

  manifest = read_manifest!(client, name)
  flow     = resolve_bound_flow!(manifest)
  params   = build_rotate_params(params_path, args)
  page_proxy = page_name ? Browserctl::PageProxy.new(page_name, client) : nil

  flow.run(page: page_proxy, client: client, **params)

  save_result = client.state_save(name,
                                  flow: flow.name,
                                  flow_version: flow.version_string,
                                  origins: manifest[:origins])
  print_result(save_result.merge(rotated_flow: flow.name))
rescue Browserctl::FlowError => e
  warn "Error: #{e.message}"
  exit 1
end

.run_save(client, args) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/browserctl/commands/state.rb', line 35

def self.run_save(client, args)
  encrypt = args.delete("--encrypt")
  origins = extract_value!(args, "--origins")
  flow    = extract_value!(args, "--flow")
  name    = args.shift or abort "usage: browserctl state save <name> [--encrypt] " \
                                "[--origins a,b] [--flow NAME]"

  passphrase = encrypt ? prompt_passphrase(confirm: true) : nil
  origin_list = parse_origins(origins)

  print_result(client.state_save(name, origins: origin_list, flow: flow, passphrase: passphrase))
end