Module: S7n::S7nCli::EntryCommandUtils

Includes:
GetText
Included in:
EntryAddCommand, EntryDeleteCommand, EntryEditCommand, EntrySearchCommand, EntryShowCommand
Defined in:
lib/s7n/s7ncli/entry_command.rb

Overview

機密情報の操作をするコマンドで使用するメソッド群。

Constant Summary collapse

EDITING_USAGE =
["-----",
_("<n>,e<n>:edit attribute a:add attribute d<n>:delete attribute"),
_("t:edit tags s:save")].join("\n")

Instance Method Summary collapse

Instance Method Details

#apply_entry_changesObject

機密情報に対する属性とタグの変更を反映させる。



290
291
292
293
294
295
296
297
298
299
# File 'lib/s7n/s7ncli/entry_command.rb', line 290

def apply_entry_changes
  @entry.tags.replace(@tags)
  d = @entry.attributes.collect(&:name) - @attributes.collect(&:name)
  if d.length > 0
    @entry.attributes.delete_if { |attr|
      attr.editable? && d.include?(attr.name)
    }
  end
  @entry.add_attributes(@attributes)
end

#command_loopObject

ユーザにコマンドの入力を促す。終了コマンドを入力するまで繰り返す。



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/s7n/s7ncli/entry_command.rb', line 140

def command_loop
  begin
    loop do
      begin
        puts("-----")
        @attributes.each.with_index do |attr, i|
          value = attr.display_value
          printf("  %2d) %s: %s\n", i, _(attr.name), value)
        end
        printf("   t) %s: %s\n", _("tags"), @tags.join(", "))
        puts("-----")
        prompt = _("Command (h:help, s:save, ^C:cancel): ")
        input = S7nCli.input_string(prompt)
        if input.nil?
          raise Interrupt
        end
        begin
          if !dispatch_command(input)
            break
          end
        rescue Interrupt
          raise Canceled
        end
      rescue ApplicationError => e
        puts(e.message)
      end
    end
  rescue Interrupt
    canceled
  end
end

#dispatch_command(input) ⇒ Object

ユーザからの入力 input を解析し、適切なコマンドを処理する。



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/s7n/s7ncli/entry_command.rb', line 173

def dispatch_command(input)
  case input
  when /\A\s*(\d+)\z/, /\Ae\s*(\d+)\z/
    index = $1.to_i
    attr = @attributes[index]
    if attr.nil?
      raise ApplicationError, _("Invalid index: %d") % index
    end
    puts(_("Edit attribute: %s") % _(attr.name))
    if attr.protected?
      name = attr.name
      secret = attr.secret?
    else
      name = input_attribute_name(attr.name)
      if name.nil?
        raise Canceled
      end
      secret = input_secret(attr.secret?)
    end
    if secret
      prompt = _("Generate value? (no): ")
      if S7nCli.input_boolean(prompt, false)
        prompt = _("Length (8): ")
        length = S7nCli.input_string(prompt).to_i
        if length <= 0
          length = 8
        end
        value = SecretGenerator.generate(length: length,
                                         characters: [:alphabet, :number])
      end
    end
    if value.nil?
      value =
        input_value(attr.display_value(secret), secret, attr.protected?)
    end
    if value.nil?
      raise Canceled
    end
    attr.name = name
    attr.secret = secret
    attr.value = value
    puts(_("Updated '%s'.") % _(attr.name))
  when "a"
    puts(_("Add attribute."))
    name = input_attribute_name
    if name.nil?
      raise Canceled
    end
    type = input_attribute_type
    if type.nil?
      raise Canceled
    end
    secret = input_secret(false)
    if secret
      prompt = _("Generate value? (no): ")
      if S7nCli.input_boolean(prompt, false)
        # TODO: pwgen コマンドを呼び出す生成機を選択できるようにする。
        prompt = _("Length (8): ")
        length = S7nCli.input_string(prompt).to_i
        if length <= 0
          length = 8
        end
        # TODO: 文字種も選べるようにする。
        value = SecretGenerator.generate(length: length)
      end
    end
    if value.nil?
      value = input_value("", secret, false)
    end
    if value.nil?
      raise Canceled
    end
    options = {
      "name" => name,
      "secret" => secret,
      "value" => value,
    }
    attr = Attribute.create_instance(type, options)
    @attributes.push(attr)
    puts(_("Added attribute: '%s'") % _(attr.name))
  when /\Ad\s*(\d+)\z/
    index = $1.to_i
    attr = @attributes[index]
    if attr.nil?
      raise ApplicationError, _("Invalid index: %d") % index
    end
    if attr.protected?
      msg = _("Can't delete attribute: %s") % _(attr.name)
      raise ApplicationError, msg
    end
    prompt = _("Delete attribute '%s'? (no): ") % _(attr.name)
    if !S7nCli.input_boolean(prompt)
      raise Canceled
    end
    @attributes.delete(attr)
    puts(_("Deleted attribute: '%s'") % _(attr.name))
  when "t"
    if input = input_tags(@tags)
      @tags = input
    else
      raise Canceled
    end
    puts(_("Updated tags."))
  when "s"
    save
    world.changed = true
    puts(_("Saved: %d") % @entry.id)
    return false
  when "h"
    puts(EDITING_USAGE)
  else
    raise ApplicationError, _("Unknown command: %s") % input
  end
  return true
end

#display_entry(entry) ⇒ Object

entry に指定した機密情報を表示する。



302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/s7n/s7ncli/entry_command.rb', line 302

def display_entry(entry)
  attr_names = entry.attributes.collect { |attr|
    _(attr.name)
  }
  n = attr_names.collect(&:length).max
  entry.attributes.each do |attr|
    secret = attr.secret? && !config["show_secret"]
    value = attr.display_value(secret)
    puts("%-#{n}s: %s" % [_(attr.name), value])
  end
  puts("%-#{n}s: %s" % [_("tag"), entry.tags.join(", ")])
end

#input_attribute_name(default = nil) ⇒ Object

ユーザに属性名を入力するように促し、入力された値を返す。



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/s7n/s7ncli/entry_command.rb', line 19

def input_attribute_name(default = nil)
  names = (@entry.attributes.collect(&:name) +
           @attributes.collect(&:name)).uniq
  if default
    s = " (#{default})"
  else
    s = ""
  end
  prompt = _("Attribute name%s: ") % s
  begin
    if input = S7nCli.input_string(prompt)
      input.strip!
      if input.empty?
        input = default
      elsif names.include?(input)
        raise ApplicationError, _("Already exist: %s") % input
      end
    end
    return input
  rescue ApplicationError => e
    puts("")
    puts(e.message)
    retry
  end
end

#input_attribute_typeObject

ユーザに属性の型の入力を促す。



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/s7n/s7ncli/entry_command.rb', line 106

def input_attribute_type
  prompt = _("Attribute type: ")
  types = Attribute.types
  Readline.completion_proc = Proc.new { |text|
    begin
      s = Readline.line_buffer.lstrip
    rescue NotImplementedError, NoMethodError
      s = text
    end
    types.select { |type|
      type =~ /\A#{s}/
    }
  }
  begin
    if input = S7nCli.input_string(prompt)
      input.strip!
      if !types.include?(input)
        raise ApplicationError, _("Unknown type: %s") % input
      end
    end
    return input
  rescue ApplicationError => e
    puts(e.message)
    puts(_("Try again."))
    retry
  ensure
    begin
      Readline.completion_proc = nil
    rescue ArgumentError
    end
  end
end

#input_secret(default) ⇒ Object

ユーザに機密情報かどうかの入力を促す。



100
101
102
103
# File 'lib/s7n/s7ncli/entry_command.rb', line 100

def input_secret(default)
  prompt = _("Is this a secret? (%s): ") % (default ? "yes" : "no")
  return S7nCli.input_boolean(prompt, default)
end

#input_tags(tags) ⇒ Object

ユーザにタグの入力を促す。入力内容を解析し、タグ名の配列を返す。 ^D を入力された場合、nil を返す。



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/s7n/s7ncli/entry_command.rb', line 85

def input_tags(tags)
  if tags.length > 0
    current = " (" + tags.join(", ") + ")"
  else
    current = ""
  end
  prompt = _("Edit tags%s: ") % current
  if input = S7nCli.input_string(prompt)
    return input.split(",").collect { |t| t.strip }
  else
    return nil
  end
end

#input_value(value, secret, protected) ⇒ Object

ユーザに属性の値を入力するように促し、入力された値を返す。 ^D を入力されて、なおかつ protected が false の場合、nil を返す。



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/s7n/s7ncli/entry_command.rb', line 47

def input_value(value, secret, protected)
  if value.length > 0
    current = _(" (%s)") % value
  else
    current = ""
  end
  prompt = _("Value%s: ") % current
  begin
    if secret
      if input = S7nCli.input_string_without_echo(prompt)
        confirmation =
          S7nCli.input_string_without_echo(_("Comfirm value: "))
        if input != confirmation
          raise ApplicationError, _("Mismatched.")
        end
      end
    else
      input = S7nCli.input_string(prompt)
    end
    if input
      input.strip! 
      if input.empty? && value
        input = value
      end
    end
    if protected && (input.nil? || input.empty?)
      raise ApplicationError, _("The value is empty.")
    end
  rescue ApplicationError => e
    puts("")
    puts(e.message + _("Try again."))
    retry
  end
  return input
end