magellan-cli 0.5.9 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4b5b5f0a5bc12049990a5c842393ce408aff9a34
4
- data.tar.gz: f4ce5c56d45a6b7fb2b17cc2620e512312a6d0ed
3
+ metadata.gz: 7db0837835cc09a010e80b50ed05ef816eac9c2d
4
+ data.tar.gz: 5eaf1c7d35daeedab002dd47d6dc1f6298846550
5
5
  SHA512:
6
- metadata.gz: 3f98e6f3f10adb66443ea4ebeaadd4ed16e45b4f875ad1dc23364bd3ed2ae6936c696cca338411ce1cc00f1ede15d7658e63d81dae79a625ac4e4484f251e90d
7
- data.tar.gz: ac3fc0570bb6e17f6c5d5efe7ae0ae09a060ba302c7b92f74b8ba8f7a769072490ec633cf0a94af332aa05c171e6589df982326645896c7ce65577b3d105c774
6
+ metadata.gz: 75ca604ec8f59c335e9eb4fe75e1ee9fff085dcb5212f7c86d47ea16a2efa7a51a2346b22d5738df7b15739a411218772658dffbb8ae6f18a755d0ed1094875e
7
+ data.tar.gz: d60150518e847386d483cd410d06bc8f02c340ffdbe43a34e51574f8023374e9b2d09c2881607be1242018cbddb6a80c5ebe36d14b0b9d32c56317a06db8367f
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
- --format documentation
1
+ --format Fuubar
2
2
  --color
data/Gemfile CHANGED
@@ -8,4 +8,5 @@ group :development do
8
8
  gem "pry-byebug"
9
9
  gem "pry-stack_explorer"
10
10
  gem "simplecov"
11
+ gem "fuubar"
11
12
  end
data/Gemfile.lock CHANGED
@@ -1,12 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- magellan-cli (0.5.9)
4
+ magellan-cli (0.6.0)
5
5
  activesupport (~> 4.1.4)
6
6
  groovenauts-thor
7
7
  httpclient (~> 2.5)
8
8
  i18n
9
- libmagellan (~> 0.2.2)
9
+ libmagellan (~> 0.2.4)
10
10
  nokogiri
11
11
  psych (>= 2.0.0, <= 2.0.8)
12
12
  text-table (~> 1.2.3)
@@ -20,7 +20,7 @@ GEM
20
20
  minitest (~> 5.1)
21
21
  thread_safe (~> 0.1)
22
22
  tzinfo (~> 1.1)
23
- addressable (2.3.6)
23
+ addressable (2.3.7)
24
24
  binding_of_caller (0.7.2)
25
25
  debug_inspector (>= 0.0.1)
26
26
  byebug (2.7.0)
@@ -34,12 +34,15 @@ GEM
34
34
  docile (1.1.5)
35
35
  faraday (0.9.1)
36
36
  multipart-post (>= 1.2, < 3)
37
+ fuubar (2.0.0)
38
+ rspec (~> 3.0)
39
+ ruby-progressbar (~> 1.4)
37
40
  groovenauts-thor (0.19.1.1)
38
41
  httpclient (2.6.0.1)
39
42
  i18n (0.7.0)
40
43
  json (1.8.2)
41
44
  jwt (1.2.1)
42
- libmagellan (0.2.3)
45
+ libmagellan (0.2.4)
43
46
  activesupport
44
47
  mqtt (~> 0.3.1)
45
48
  signet (~> 0.5.0)
@@ -75,6 +78,7 @@ GEM
75
78
  rspec-mocks (3.0.4)
76
79
  rspec-support (~> 3.0.0)
77
80
  rspec-support (3.0.4)
81
+ ruby-progressbar (1.7.1)
78
82
  signet (0.5.1)
79
83
  addressable (>= 2.2.3)
80
84
  faraday (>= 0.9.0.rc5)
@@ -96,6 +100,7 @@ PLATFORMS
96
100
 
97
101
  DEPENDENCIES
98
102
  bundler (~> 1.6)
103
+ fuubar
99
104
  magellan-cli!
100
105
  pry
101
106
  pry-byebug
data/lib/magellan/cli.rb CHANGED
@@ -6,11 +6,10 @@ module Magellan
6
6
  autoload :Command , "magellan/cli/command"
7
7
 
8
8
  autoload :Base , "magellan/cli/base"
9
- autoload :Http , "magellan/cli/http"
10
9
  autoload :Direct , "magellan/cli/direct"
11
10
  autoload :Resources, "magellan/cli/resources"
12
11
 
13
- autoload :Login , "magellan/cli/login"
12
+ autoload :Http , "magellan/cli/http"
14
13
  autoload :Ssl , "magellan/cli/ssl"
15
14
 
16
15
  autoload :Messaging, "magellan/cli/messaging"
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  require "magellan/cli"
2
3
 
3
4
  require 'thor'
@@ -36,6 +37,9 @@ module Magellan
36
37
  def log_info(msg)
37
38
  self.class.log_info(msg)
38
39
  end
40
+ def log_warning(msg)
41
+ self.class.log_warning(msg)
42
+ end
39
43
  def log_success(msg)
40
44
  self.class.log_success(msg)
41
45
  end
@@ -53,8 +57,104 @@ module Magellan
53
57
  log_verbose(" " << e.backtrace.join("\n "))
54
58
  exit(1)
55
59
  end
60
+
61
+ def http_conn
62
+ @http_conn ||= Cli::Http.new(self)
63
+ end
64
+
65
+ def login!(email, password)
66
+ logined = http_conn.api_login!(email, password)
67
+ if logined
68
+ log_success I18n.t(:success, scope: [:http, :login])
69
+ else
70
+ log_error I18n.t(:error, scope: [:http, :login])
71
+ exit(1)
72
+ end
73
+ end
74
+
75
+ def login_by_token!(email, token)
76
+ logined = http_conn.api_login_by_token!(email, token)
77
+ if logined
78
+ log_success I18n.t(:success, scope: [:http, :token])
79
+ else
80
+ log_error I18n.t(:error, scope: [:http, :token])
81
+ exit(1)
82
+ end
83
+ end
84
+
85
+ def http_access
86
+ if block_given?
87
+ http_conn.check_login_auth!
88
+ return yield(http_conn)
89
+ else
90
+ return log_success(I18n.t(:ok, scope: [:http, :access_api]))
91
+ end
92
+ end
93
+
94
+
95
+ # ログインしてGETします
96
+ # @param [String] rel_path http.base_url からの相対パス
97
+ # @param [Hash] params クエリ文字列
98
+ # @return [Object] レスポンスのBODYをJSONとしてパースした結果オブジェクト
99
+ def get_json(rel_path, params = {})
100
+ http_access do |api|
101
+ api.get_json(rel_path, params = {})
102
+ end
103
+ end
104
+
105
+ # ログインしてPOSTします
106
+ # @param [String] rel_path http.base_url からの相対パス
107
+ # @param [Hash] params POSTで渡されるパラメータ
108
+ # @return nil
109
+ def post(rel_path, params)
110
+ http_access do |api|
111
+ api.post(rel_path, params)
112
+ end
113
+ end
114
+
115
+ # ログインしてJSON形式のbodyをPOSTします
116
+ # @param [String] rel_path http.base_url からの相対パス
117
+ # @param [Hash] params POSTで渡されるパラメータ
118
+ # @return nil
119
+ def post_json(rel_path, params)
120
+ http_access do |api|
121
+ api.post_json(rel_path, params)
122
+ end
123
+ end
124
+
125
+ # ログインしてPUTします
126
+ # @param [String] rel_path http.base_url からの相対パス
127
+ # @param [Hash] params PUTで渡されるパラメータ
128
+ # @return nil
129
+ def put(rel_path, params)
130
+ http_access do |api|
131
+ api.put(rel_path, params)
132
+ end
133
+ end
134
+
135
+ # ログインしてJSON形式のbodyをPUTします
136
+ # @param [String] rel_path http.base_url からの相対パス
137
+ # @param [Hash] params PUTで渡されるパラメータ
138
+ # @return nil
139
+ def put_json(rel_path, params)
140
+ http_access do |api|
141
+ api.put_json(rel_path, params)
142
+ end
143
+ end
144
+
145
+ # ログインしてDELETEします
146
+ # @param [String] rel_path http.base_url からの相対パス
147
+ # @return nil
148
+ def delete(rel_path)
149
+ http_access do |api|
150
+ api.delete(rel_path)
151
+ end
152
+ end
153
+
56
154
  end
57
155
 
156
+
157
+
58
158
  class << self
59
159
  def puts_with_color(color_no, msg)
60
160
  $stderr.puts("\e[#{color_no}m#{msg}\e[0m")
@@ -66,6 +166,9 @@ module Magellan
66
166
  def log_info(msg)
67
167
  puts_with_color(0, msg)
68
168
  end
169
+ def log_warning(msg)
170
+ puts_with_color(33, msg)
171
+ end
69
172
  def log_success(msg)
70
173
  puts_with_color(32, msg)
71
174
  end
@@ -160,4 +263,3 @@ module Magellan
160
263
  end
161
264
  end
162
265
  end
163
-
@@ -69,29 +69,45 @@ module Magellan
69
69
  desc "login", I18n.t(:login, scope: [:command, :cmd])
70
70
  method_option :email, aliases: "-e", desc: I18n.t(:email, scope: [:command, :cmd_login])
71
71
  method_option :password, aliases: "-p", desc: I18n.t(:password, scope: [:command, :cmd_login])
72
+ method_option :authentication_token, aliases: "-t", desc: I18n.t(:authentication_token, scope: [:command, :cmd_login])
72
73
  def login
73
74
  unless email = options[:email]
74
75
  print "email: "
75
76
  email = STDIN.gets.strip
76
77
  end
77
78
 
78
- unless password = options[:password]
79
+ password = options[:password]
80
+ token = options[:authentication_token]
81
+
82
+ if password.blank? && token.blank?
83
+ log_warning I18n.t(:warning, scope: :login)
79
84
  print "password: "
80
85
  password = STDIN.noecho(&:gets).chomp
81
86
  puts ""
82
87
  end
83
88
 
84
- result = Magellan::Cli::Http.new.login!(email, password)
89
+ if password.blank? && token.blank?
90
+ print "authentication_token: "
91
+ token = STDIN.noecho(&:gets).chomp
92
+ puts ""
93
+ end
94
+
95
+ result =
96
+ if password.present?
97
+ login!(email, password)
98
+ else
99
+ login_by_token!(email, token)
100
+ end
101
+
85
102
  select_single_resources
86
103
  result
87
104
  end
88
105
 
89
106
  desc "info", I18n.t(:info, scope: [:command, :cmd])
90
107
  def info
91
- cli = Magellan::Cli::Login.new
92
- cli.check_login_auth!
108
+ http_conn.check_login_auth!
93
109
  selections = load_selections || {}
94
- d = {"user" => cli.login_auth["email"] }
110
+ d = {"user" => http_conn.login_auth["email"] }
95
111
  Resources::MAPPING.each do |classname, name|
96
112
  klass = ::Magellan::Cli::Resources.const_get(classname)
97
113
  attr = klass.caption_attr
@@ -3,7 +3,7 @@ require "magellan/cli"
3
3
 
4
4
  module Magellan
5
5
  module Cli
6
- class Direct < ::Magellan::Cli::Http
6
+ class Direct < ::Magellan::Cli::Base
7
7
 
8
8
  desc "get PATH", "Send GET request with PATH"
9
9
  def get(path)
@@ -29,4 +29,3 @@ module Magellan
29
29
  end
30
30
  end
31
31
  end
32
-
@@ -1,149 +1,257 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require "magellan/cli"
3
3
 
4
+ require 'httpclient'
5
+ require 'json'
6
+ require 'uri'
7
+ require 'nokogiri'
8
+
9
+ require 'active_support/core_ext/hash/keys'
10
+
4
11
  module Magellan
5
12
  module Cli
6
- class Http < ::Magellan::Cli::Base
13
+ class Http
14
+ include Magellan::Cli::FileAccess
7
15
 
8
- no_commands do
16
+ DEFAULT_HTTP_PORT = (ENV['DEFAULT_HTTP_PORT' ] || 80).to_i
17
+ DEFAULT_HTTPS_PORT = (ENV['DEFAULT_HTTPS_PORT'] || 443).to_i
9
18
 
10
- def cli
11
- @cli ||= Cli::Login.new
12
- end
19
+ attr_reader :cmd
20
+ attr_reader :httpclient
21
+ attr_reader :base_url
13
22
 
14
- def login!(email, password)
15
- logined = cli.api_login!(email, password)
16
- if logined
17
- log_success I18n.t(:success, scope: [:http, :login])
18
- else
19
- log_error I18n.t(:error, scope: [:http, :login])
20
- exit(1)
21
- end
22
- end
23
+ attr_reader :auth_token
24
+ attr_reader :login_auth
25
+
26
+ def self.base_url
27
+ @base_url ||= (ENV["MAGELLAN_SITE"] || "https://api-asia.magellanic-clouds.com")
28
+ end
23
29
 
24
- def access_api
25
- if block_given?
26
- cli.check_login_auth!
27
- return yield(cli)
30
+ # Magellan::Cli::Httpのコンストラクタです。
31
+ #
32
+ # @param [String] base_url_or_host 接続先の基準となるURLあるいはホスト名
33
+ # @param [Hash] options オプション
34
+ # @option options [String] :api_version APIのバージョン。デフォルトは "1.0.0"
35
+ def initialize(cmd)
36
+ @cmd = cmd
37
+ base_url_or_host = self.class.base_url
38
+ if base_url_or_host =~ URI.regexp
39
+ @base_url = base_url_or_host.sub(/\/\Z/, '')
40
+ uri = URI.parse(@base_url)
41
+ else
42
+ if config_path = search_file(".magellan-cli.yml")
43
+ config = YAML.load_file_with_erb(config_path)
44
+ options = config[base_url_or_host.to_s].deep_symbolize_keys
28
45
  else
29
- return log_success(I18n.t(:ok, scope: [:http, :access_api]))
46
+ options = {}
30
47
  end
48
+ uri = URI::Generic.build({scheme: "http", host: base_url_or_host, port: DEFAULT_HTTP_PORT}.update(options))
49
+ @base_url = uri.to_s
31
50
  end
32
51
 
33
- def check_response(res)
34
- case res.status
35
- when 200...400 then
36
- begin
37
- r = JSON.parse(res.body)
38
- rescue
39
- # DELETE で 302 Found を返す時に HTML がレンダリングされることがあるので
40
- # status code 300 台では JSON パースエラーを無視する
41
- if res.status >= 300
42
- return nil
43
- end
44
- raise
45
- end
46
- log_verbose(JSON.pretty_generate(r))
47
- r
48
- else
49
- obj = JSON.parse(res.body) rescue nil
50
- if obj and obj.is_a?(Hash) and obj["message"]
51
- fatal(obj["message"])
52
- else
53
- msg = "HTTP Error: status=#{res.status}\n#{res.body}"
54
- log_verbose(msg)
55
- end
56
- end
52
+ @httpclient = HTTPClient.new
53
+ @httpclient.debug_dev = ColorDebugDev.new($stderr) if cmd.verbose?
54
+ @httpclient.ssl_config.verify_mode = nil # 自己署名の証明書をOKにする
55
+ @login_auth = load_selections["login"]
56
+ end
57
+
58
+ class ColorDebugDev
59
+ def initialize(dev)
60
+ @dev = dev
61
+ end
62
+ def <<(msg)
63
+ @dev << "\e[34m#{msg}\e[0m"
57
64
  end
65
+ end
58
66
 
59
- # ログインしてGETします
60
- # @param [String] rel_path cli.base_url からの相対パス
61
- # @param [Hash] params クエリ文字列
62
- # @return [Object] レスポンスのBODYをJSONとしてパースした結果オブジェクト
63
- def get_json(rel_path, params = {})
64
- access_api do |api|
65
- url = "#{api.base_url}#{rel_path}"
66
- params.update(yield) if block_given?
67
- params = api.login_auth.merge(params)
68
- if params && !params.empty?
69
- url << '?' << params.map{|k,v| "%s=%s" % [CGI.escape(k.to_s), CGI.escape(v.to_s)] }.join("&")
70
- end
71
- log_verbose("GET #{url}")
72
- # "Unknown key: max-age = 0" というメッセージを表示させないために$stderrを一時的に上書き
73
- $stderr, bak = StringIO.new, $stderr
74
- res = nil
75
- begin
76
- res = api.httpclient.get(url)
77
- ensure
78
- $stderr = bak
79
- end
80
- check_response(res)
81
- end
67
+ def login_form_url
68
+ @login_form_url ||= base_url + "/users/sign_in.html"
69
+ end
70
+ def login_url
71
+ @login_url ||= base_url + "/api/sign_in.json"
72
+ end
73
+
74
+ def check_login_auth!
75
+ auth = login_auth
76
+ if auth.nil? || auth.empty?
77
+ raise Magellan::Cli::Error, I18n.t(:not_logged_in, scope: [:login, :check_login_auth], command: File.basename($0))
82
78
  end
79
+ end
83
80
 
84
- # ログインしてPOSTします
85
- # @param [String] rel_path cli.base_url からの相対パス
86
- # @param [Hash] params POSTで渡されるパラメータ
87
- # @return nil
88
- def post(rel_path, params)
89
- access_api do |api|
90
- params = api.login_auth.update(params || {})
91
- process_res(api, :post, rel_path, params)
92
- end
81
+ # magellan-apiサーバに接続してログインの検証とアクセストークンの保存を行います。
82
+ #
83
+ # @return [boolean] login成功/失敗
84
+ def api_login!(email, password)
85
+ @auth_token ||= get_auth_token
86
+ params = {
87
+ "user" => {
88
+ "email" => email,
89
+ "password" => password
90
+ },
91
+ "authenticity_token" => @auth_token
92
+ }.to_json
93
+ res2 = Ssl.retry_on_ssl_error("login"){ @httpclient.post(login_url, params, JSON_HEADER) }
94
+
95
+ case res2.status
96
+ when 200...300 then logined = true
97
+ else logined = false
93
98
  end
94
99
 
95
- # ログインしてJSON形式のbodyをPOSTします
96
- # @param [String] rel_path cli.base_url からの相対パス
97
- # @param [Hash] params POSTで渡されるパラメータ
98
- # @return nil
99
- def post_json(rel_path, params)
100
- access_api do |api|
101
- params = api.login_auth.update(params || {})
102
- process_res(api, :post, rel_path, params.to_json, JSON_HEADER)
103
- end
100
+ if logined
101
+ body = JSON.parse res2.body
102
+ write_login_info!(email, body["token"])
103
+ else
104
+ reset_login_info!
104
105
  end
106
+ logined
107
+ end
105
108
 
106
- # ログインしてPUTします
107
- # @param [String] rel_path cli.base_url からの相対パス
108
- # @param [Hash] params PUTで渡されるパラメータ
109
- # @return nil
110
- def put(rel_path, params)
111
- access_api do |api|
112
- params = api.login_auth.update(params || {})
113
- process_res(api, :put, rel_path, params)
109
+ def api_login_by_token!(email, token)
110
+ url = "#{base_url}/admin/magellan~auth~organization.json"
111
+ params = {"email" => email, "token" => token}
112
+ res = httpclient.get(url, params)
113
+
114
+ logined =
115
+ case res.status
116
+ when 200...400 then true
117
+ else false
114
118
  end
119
+
120
+ if logined
121
+ write_login_info!(email, token)
122
+ else
123
+ reset_login_info!
115
124
  end
125
+ logined
126
+ end
116
127
 
117
- # ログインしてJSON形式のbodyをPUTします
118
- # @param [String] rel_path cli.base_url からの相対パス
119
- # @param [Hash] params PUTで渡されるパラメータ
120
- # @return nil
121
- def put_json(rel_path, params)
122
- access_api do |api|
123
- params = api.login_auth.update(params || {})
124
- process_res(api, :put, rel_path, params.to_json, JSON_HEADER)
125
- end
128
+
129
+ def write_login_info!(email, token)
130
+ update_selections("login" => {"email" => email, "token" => token })
131
+ end
132
+
133
+ def reset_login_info!
134
+ update_selections("login" => nil)
135
+ end
136
+
137
+ def get_auth_token
138
+ res = Ssl.retry_on_ssl_error("login_form"){ @httpclient.get(login_form_url) }
139
+ doc = Nokogiri::HTML.parse(res.body, login_form_url, res.body_encoding.to_s)
140
+ node = doc.xpath('//input[@name="authenticity_token"]').first
141
+ unless node
142
+ raise Cli::Error.new("fail to login Magellan")
126
143
  end
144
+ node.attribute('value').value
145
+ end
127
146
 
128
- # ログインしてDELETEします
129
- # @param [String] rel_path cli.base_url からの相対パス
130
- # @return nil
131
- def delete(rel_path)
132
- access_api do |api|
133
- params = api.login_auth
134
- process_res(api, :delete, rel_path, params.to_json, JSON_HEADER)
147
+ # @httpclient.inspectの戻り値の文字列が巨大なので、inspectで出力しないようにします。
148
+ def inspect
149
+ r = "#<#{self.class.name}:#{self.object_id} "
150
+ fields = (instance_variables - [:@httpclient]).map{|f| "#{f}=#{instance_variable_get(f).inspect}"}
151
+ r << fields.join(", ") << ">"
152
+ end
153
+
154
+ def search_file(basename)
155
+ dirs = [".", "./config", ENV['HOME']].join(",")
156
+ Dir["{#{dirs}}/#{basename}"].select{|path| File.readable?(path)}.first
157
+ end
158
+ private :search_file
159
+
160
+
161
+ def check_response(res)
162
+ case res.status
163
+ when 200...400 then
164
+ begin
165
+ r = JSON.parse(res.body)
166
+ rescue
167
+ # DELETE で 302 Found を返す時に HTML がレンダリングされることがあるので
168
+ # status code 300 台では JSON パースエラーを無視する
169
+ if res.status >= 300
170
+ return nil
171
+ end
172
+ raise
173
+ end
174
+ r
175
+ else
176
+ obj = JSON.parse(res.body) rescue nil
177
+ if obj and obj.is_a?(Hash) and obj["message"]
178
+ fatal(obj["message"])
135
179
  end
136
180
  end
181
+ end
137
182
 
138
- def process_res(api, http_method, rel_path, *args)
139
- url = "#{api.base_url}#{rel_path}"
140
- log_verbose("%s %s\n%s" % [http_method.to_s.upcase, url, args])
141
- res = api.httpclient.send(http_method, url, *args)
142
- check_response(res)
183
+ # ログインしてGETします
184
+ # @param [String] rel_path cli.base_url からの相対パス
185
+ # @param [Hash] params クエリ文字列
186
+ # @return [Object] レスポンスのBODYをJSONとしてパースした結果オブジェクト
187
+ def get_json(rel_path, params = {})
188
+ url = "#{base_url}#{rel_path}"
189
+ params.update(yield) if block_given?
190
+ params = login_auth.merge(params)
191
+ if params && !params.empty?
192
+ url << '?' << params.map{|k,v| "%s=%s" % [CGI.escape(k.to_s), CGI.escape(v.to_s)] }.join("&")
193
+ end
194
+ # "Unknown key: max-age = 0" というメッセージを表示させないために$stderrを一時的に上書き
195
+ $stderr, bak = StringIO.new, $stderr
196
+ res = nil
197
+ begin
198
+ res = httpclient.get(url)
199
+ ensure
200
+ $stderr = bak
143
201
  end
202
+ check_response(res)
203
+ end
204
+
205
+ # ログインしてPOSTします
206
+ # @param [String] rel_path cli.base_url からの相対パス
207
+ # @param [Hash] params POSTで渡されるパラメータ
208
+ # @return nil
209
+ def post(rel_path, params)
210
+ params = login_auth.update(params || {})
211
+ process_res(:post, rel_path, params)
212
+ end
213
+
214
+ # ログインしてJSON形式のbodyをPOSTします
215
+ # @param [String] rel_path cli.base_url からの相対パス
216
+ # @param [Hash] params POSTで渡されるパラメータ
217
+ # @return nil
218
+ def post_json(rel_path, params)
219
+ params = login_auth.update(params || {})
220
+ process_res(:post, rel_path, params.to_json, JSON_HEADER)
221
+ end
144
222
 
223
+ # ログインしてPUTします
224
+ # @param [String] rel_path cli.base_url からの相対パス
225
+ # @param [Hash] params PUTで渡されるパラメータ
226
+ # @return nil
227
+ def put(rel_path, params)
228
+ params = login_auth.update(params || {})
229
+ process_res(:put, rel_path, params)
145
230
  end
231
+
232
+ # ログインしてJSON形式のbodyをPUTします
233
+ # @param [String] rel_path cli.base_url からの相対パス
234
+ # @param [Hash] params PUTで渡されるパラメータ
235
+ # @return nil
236
+ def put_json(rel_path, params)
237
+ params = login_auth.update(params || {})
238
+ process_res(:put, rel_path, params.to_json, JSON_HEADER)
239
+ end
240
+
241
+ # ログインしてDELETEします
242
+ # @param [String] rel_path cli.base_url からの相対パス
243
+ # @return nil
244
+ def delete(rel_path)
245
+ params = login_auth
246
+ process_res(:delete, rel_path, params.to_json, JSON_HEADER)
247
+ end
248
+
249
+ def process_res(http_method, rel_path, *args)
250
+ url = "#{base_url}#{rel_path}"
251
+ res = httpclient.send(http_method, url, *args)
252
+ check_response(res)
253
+ end
254
+
146
255
  end
147
256
  end
148
257
  end
149
-
@@ -32,6 +32,7 @@ en:
32
32
  cmd_login:
33
33
  email: "email address for login"
34
34
  password: "password for login"
35
+ authentication_token: "authentication token for login"
35
36
  cmd_help:
36
37
  for_more_detail: "type `%{command} help RESOURCE` for more detail"
37
38
  file_access:
@@ -43,9 +44,13 @@ en:
43
44
  error: "Login failure"
44
45
  access_api:
45
46
  ok: "OK"
47
+ token:
48
+ success: "Authorized"
49
+ error: "Unauthorized"
46
50
  login:
47
51
  check_login_auth:
48
52
  not_logged_in: "Not logined yet. type `%{command} login`."
53
+ warning: "Please refer to the password empty if you want to login with authentication token."
49
54
  messaging:
50
55
  http:
51
56
  ping: "Send a HTTP request to check connection"
@@ -30,6 +30,7 @@ ja:
30
30
  cmd_login:
31
31
  email: "ログインするアカウントのメールアドレス"
32
32
  password: "ログインするアカウントのパスワード"
33
+ authentication_token: "ログインするアカウントの認証トークン"
33
34
  cmd_help:
34
35
  for_more_detail: "詳しくは `%{command} help RESOURCE` を実行してください"
35
36
  file_access:
@@ -41,9 +42,13 @@ ja:
41
42
  error: "ログインに失敗しました"
42
43
  access_api:
43
44
  ok: "OK"
45
+ token:
46
+ success: "認証しました"
47
+ error: "認証に失敗しました"
44
48
  login:
45
49
  check_login_auth:
46
50
  not_logged_in: "ログインしていません。`%{command} login` を実行してログインしてください"
51
+ warning: "認証トークンでログインする場合はパスワードを空にしてください"
47
52
  messaging:
48
53
  http:
49
54
  ping: "接続確認のリクエストを送信します"
@@ -7,7 +7,7 @@ require 'yaml'
7
7
  module Magellan
8
8
  module Cli
9
9
  module Messaging
10
- class Base < Magellan::Cli::Http
10
+ class Base < Magellan::Cli::Base
11
11
  include Magellan::Cli::FileAccess
12
12
 
13
13
  no_commands do
@@ -18,7 +18,7 @@ module Magellan
18
18
  private
19
19
 
20
20
  def load_selection!(name, &block)
21
- return access_api{ load_selection(name, &block) }
21
+ return http_access{ load_selection(name, &block) }
22
22
  end
23
23
 
24
24
  def find(klass, id = nil)
@@ -39,6 +39,7 @@ module Magellan
39
39
  client_version: client_version,
40
40
  mqtt_host: ENV["MAGELLAN_MQTT_SERVER_HOST"] || DEFAULT_MAGELLAN_MQTT_SERVER_HOST,
41
41
  mqtt_port: ENV["MAGELLAN_MQTT_SERVER_PORT"] || DEFAULT_MAGELLAN_MQTT_SERVER_PORT,
42
+ verbose: options[:verbose],
42
43
  }
43
44
  uri = ENV["MAGELLAN_HTTP_SERVER_URL"] || DEFAULT_MAGELLAN_HTTP_SERVER_URL
44
45
  log_verbose("HTTP URL : #{uri.inspect}")
@@ -17,16 +17,16 @@ module Magellan
17
17
  class NotFound < Magellan::Cli::Error
18
18
  end
19
19
 
20
- class Base < ::Magellan::Cli::Http
20
+ class Base < ::Magellan::Cli::Base
21
21
  include Magellan::Cli::FileAccess
22
22
 
23
23
  no_commands do
24
24
 
25
25
  def load_selection!(name, &block)
26
- return access_api{ load_selection(name, &block) }
26
+ return http_access{ load_selection(name, &block) }
27
27
  end
28
28
  def update_selections!(hash = nil, &block)
29
- return access_api{ update_selections(hash, &block) }
29
+ return http_access{ update_selections(hash, &block) }
30
30
  end
31
31
 
32
32
  def build_query(hash)
@@ -41,7 +41,7 @@ module Magellan
41
41
  end
42
42
 
43
43
  def default_query
44
- access_api do |cli|
44
+ http_access do |cli|
45
45
  sel = load_selections
46
46
  q = {}
47
47
  (self.class.resource_dependency || {}).each do |f, res|
@@ -169,6 +169,9 @@ module Magellan
169
169
  def select(name)
170
170
  q = build_query(self.class.caption_attr => name).update(default_query)
171
171
  update_first_result(self.class.parameter_name, name, "/admin/#{self.class.resource_key}.json", q)
172
+ update_selections! do |s|
173
+ self.class.deselect_dependants(s)
174
+ end
172
175
  end
173
176
 
174
177
  def deselect
@@ -16,6 +16,7 @@ module Magellan
16
16
  self.caption_attr = "version"
17
17
 
18
18
  desc "create VERSION", I18n.t(:create, scope: [:resources, :client_version, :cmd], resource_name: resource_name)
19
+ method_option :domain, aliases: "-d", desc: I18n.t(:domain, scope: [:resources, :client_version, :cmd_create])
19
20
  def create(version)
20
21
  project = load_selection!(Project)
21
22
  stage = load_selection!(Stage)
@@ -24,12 +25,31 @@ module Magellan
24
25
  "stage_title_id" => stage["id"],
25
26
  "version" => version,
26
27
  }
28
+ if d = options[:domain]
29
+ attrs["domain"] = d
30
+ end
27
31
  params = { parameter_name => attrs }
28
32
  post_json("/admin/#{resource_key}/new.json", params)
29
33
  # TODO implement select method
30
34
  # select(version)
31
35
  end
32
36
 
37
+ desc "update ATTRIBUTES", I18n.t(:update, scope: [:resources, :client_version, :cmd], resource_name: resource_name)
38
+ def update(attrs)
39
+ if File.readable?(attrs)
40
+ attrs = YAML.load_file(attrs)
41
+ else
42
+ attrs = JSON.parse(attrs)
43
+ end
44
+ cv = load_selection!(self.class)
45
+ self.class.hidden_fields.each do |f| attrs.delete(f) end
46
+ self.class.field_associations.keys.each do |f| attrs.delete(f) end
47
+ params = {
48
+ parameter_name => attrs
49
+ }
50
+ put_json("/admin/#{resource_key}/#{cv["id"]}/edit.json", params)
51
+ end
52
+
33
53
  desc "delete VERSION", I18n.t(:delete, scope: [:resources, :client_version, :cmd], resource_name: resource_name)
34
54
  def delete(version)
35
55
  q = build_query("version" => version).update(default_query)
@@ -1,5 +1,5 @@
1
1
  module Magellan
2
2
  module Cli
3
- VERSION = "0.5.9"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
data/magellan-cli.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_runtime_dependency "text-table", "~> 1.2.3"
26
26
  spec.add_runtime_dependency "i18n"
27
27
  spec.add_runtime_dependency "psych", ">= 2.0.0", "<= 2.0.8"
28
- spec.add_runtime_dependency "libmagellan", "~> 0.2.2"
28
+ spec.add_runtime_dependency "libmagellan", "~> 0.2.4"
29
29
 
30
30
  spec.add_development_dependency "bundler", "~> 1.6"
31
31
  spec.add_development_dependency "rake", "~> 10.0"
@@ -10,7 +10,8 @@ describe Magellan::Cli::Command do
10
10
  before do
11
11
  $stdout = StringIO.new
12
12
  allow(command).to receive(:select_single_resources)
13
- allow(Magellan::Cli::Http).to receive_message_chain(:new, :login!).and_return("OK")
13
+ allow(command).to receive(:login!).and_return("OK")
14
+ allow(command).to receive(:login_by_token!).and_return("OK")
14
15
  end
15
16
  it "nothing options" do
16
17
  allow($stdin).to receive(:gets).and_return(string).once
@@ -19,6 +20,13 @@ describe Magellan::Cli::Command do
19
20
  expect($stdout.string).to eq "email: password: \n"
20
21
  end
21
22
 
23
+ it "nothing options" do
24
+ allow($stdin).to receive(:gets ).and_return(string).once # email
25
+ allow($stdin).to receive(:noecho).and_return("\n").twice # password
26
+ expect(command.login).to eq "OK"
27
+ expect($stdout.string).to eq "email: password: \nauthentication_token: \n"
28
+ end
29
+
22
30
  it "only email" do
23
31
  allow($stdin).to receive(:noecho).and_return(string).twice
24
32
  command.options = Thor::CoreExt::HashWithIndifferentAccess.new email: string
@@ -32,6 +40,13 @@ describe Magellan::Cli::Command do
32
40
  expect(command.login).to eq "OK"
33
41
  expect($stdout.string).to eq "email: "
34
42
  end
43
+
44
+ it "only authentication_token" do
45
+ allow($stdin).to receive(:gets).and_return(string).once
46
+ command.options = Thor::CoreExt::HashWithIndifferentAccess.new authentication_token: string
47
+ expect(command.login).to eq "OK"
48
+ expect($stdout.string).to eq "email: "
49
+ end
35
50
  end
36
51
  end
37
52
  end
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe Magellan::Cli::Messaging::Http do
5
+
6
+ let(:cmd){ Magellan::Cli::Messaging::Http.new }
7
+
8
+ describe :login_by_token do
9
+ let(:email) { "user1@example.com" }
10
+ let(:password) { "password" }
11
+ let(:success_res) { double(:success_res, status: 200) }
12
+ let(:error_res) { double(:error_res, status: 401) }
13
+
14
+ it "success" do
15
+ allow(cmd.http_conn.httpclient).to receive(:get).and_return(success_res)
16
+ cmd.login_by_token!(email, password)
17
+ end
18
+
19
+ it "error" do
20
+ allow(cmd.http_conn.httpclient).to receive(:get).and_return(error_res)
21
+ expect{cmd.login_by_token!(email, password)}.to raise_error(SystemExit)
22
+ end
23
+ end
24
+ end
@@ -1,12 +1,17 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'spec_helper'
3
3
 
4
- describe Magellan::Cli::Login do
4
+ describe Magellan::Cli::Http do
5
5
 
6
6
  describe :login! do
7
7
  let(:email){ "magellan@groovenauts.jp" }
8
8
  let(:password){ "password" }
9
9
  let(:auth_token){ "047bcCC1dnyVE+7DWE6YKIJF97L/qHk1mPrf2oaqWtE=" }
10
+ let(:cmd) do
11
+ cmd = double(:cmd)
12
+ allow(cmd).to receive(:verbose?).and_return(false)
13
+ cmd
14
+ end
10
15
 
11
16
  before do
12
17
  allow(File).to receive(:readable?).and_return(true)
@@ -14,7 +19,8 @@ describe Magellan::Cli::Login do
14
19
  end
15
20
 
16
21
  context :production do
17
- let(:cli){ Magellan::Cli::Login.new("https://example.com") }
22
+ before{ allow(Magellan::Cli::Http).to receive(:base_url).and_return("https://example.com") }
23
+ let(:cli){ Magellan::Cli::Http.new(cmd) }
18
24
  before do
19
25
  res = double(:res)
20
26
  allow(cli.httpclient).to receive(:get).with("https://example.com/users/sign_in.html").and_return(res)
@@ -50,7 +56,8 @@ describe Magellan::Cli::Login do
50
56
  end
51
57
 
52
58
  context :development do
53
- let(:cli){ Magellan::Cli::Login.new("http://localhost:3001") }
59
+ before{ allow(Magellan::Cli::Http).to receive(:base_url).and_return("http://localhost:3001") }
60
+ let(:cli){ Magellan::Cli::Http.new(cmd) }
54
61
  before do
55
62
  res = double(:res)
56
63
  allow(cli.httpclient).to receive(:get).with("http://localhost:3001/users/sign_in.html").and_return(res)
@@ -5,8 +5,8 @@ describe Magellan::Cli::Resources::ClientVersion do
5
5
 
6
6
  let(:cmd){ Magellan::Cli::Resources::ClientVersion.new }
7
7
 
8
- let(:cli){ double(:cli, :check_login_auth! => nil) }
9
- before{ allow(cmd).to receive(:cli).and_return(cli) }
8
+ let(:http_conn){ double(:http_conn, :check_login_auth! => nil) }
9
+ before{ allow(cmd).to receive(:http_conn).and_return(http_conn) }
10
10
 
11
11
  describe :list do
12
12
  before do
@@ -33,6 +33,17 @@ describe Magellan::Cli::Resources::ClientVersion do
33
33
  end
34
34
  end
35
35
 
36
+ describe :success_with_domain do
37
+ before do
38
+ allow(cmd).to receive(:load_selections).and_return({Magellan::Cli::Resources::Project.parameter_name => {"id" => 1, "name" => "ProjectA"}, Magellan::Cli::Resources::Stage.parameter_name => {"id" => 1, "name" => "StageA"} })
39
+ expect(cmd).to receive(:post_json).with("/admin/client_version/new.json", { "client_version" => { "project_id" => 1, "stage_title_id" => 1, "version" => "1.1.0", "domain" => "foo.example.com" } })
40
+ end
41
+ it do
42
+ cmd.options = {domain: "foo.example.com"}
43
+ cmd.create("1.1.0")
44
+ end
45
+ end
46
+
36
47
  describe :error do
37
48
  context "stage not selected" do
38
49
  before do
@@ -47,4 +58,22 @@ describe Magellan::Cli::Resources::ClientVersion do
47
58
  end
48
59
  end
49
60
 
61
+ describe :update do
62
+ let(:selections) do
63
+ {
64
+ Magellan::Cli::Resources::Project.parameter_name => {"id" => 1, "name" => "ProjectA"},
65
+ Magellan::Cli::Resources::ClientVersion.parameter_name => {"id" => 1, "version" => "Sandbox1"}
66
+ }
67
+ end
68
+ describe :success_to_update_domain do
69
+ before do
70
+ allow(cmd).to receive(:load_selections).and_return(selections)
71
+ expect(cmd).to receive(:put_json).with("/admin/client_version/1/edit.json", { "client_version" => { "domain" => "bar.example.com" } })
72
+ end
73
+ it do
74
+ cmd.update('{"domain": "bar.example.com"}')
75
+ end
76
+ end
77
+ end
78
+
50
79
  end
@@ -65,4 +65,17 @@ describe "deselect" do
65
65
  end
66
66
  end
67
67
 
68
+ describe Magellan::Cli::Resources::Organization do
69
+ context "select another one" do
70
+ it do
71
+ allow(subject).to receive(:get_json).
72
+ with("/admin/magellan~auth~organization.json", an_instance_of(Hash)).
73
+ and_return([{"id" => 5, "name" => "test3"}])
74
+ expect(YAML.load_file(work_yaml)).to include(Magellan::Cli::Resources::Project.parameter_name)
75
+ subject.select "test3"
76
+ expect(YAML.load_file(work_yaml)).to_not include(Magellan::Cli::Resources::Project.parameter_name)
77
+ end
78
+ end
79
+ end
80
+
68
81
  end
@@ -5,8 +5,8 @@ describe Magellan::Cli::Resources::Organization do
5
5
 
6
6
  let(:cmd){ Magellan::Cli::Resources::Organization.new }
7
7
 
8
- let(:cli){ double(:cli, :check_login_auth! => nil) }
9
- before{ allow(cmd).to receive(:cli).and_return(cli) }
8
+ let(:http_conn){ double(:http_conn, :check_login_auth! => nil) }
9
+ before{ allow(cmd).to receive(:http_conn).and_return(http_conn) }
10
10
 
11
11
  describe :list do
12
12
  before do
@@ -4,23 +4,21 @@ require 'spec_helper'
4
4
  describe Magellan::Cli::Resources::Project do
5
5
 
6
6
  let(:base_url){ "https://localhost:3000" }
7
+ before{ allow(Magellan::Cli::Http).to receive(:base_url).and_return(base_url) }
7
8
  let(:httpclient){ double(:httpclient) }
8
- let(:cli) do
9
- cli = double(:access_api, base_url: base_url, auth_token: {}, login_auth: {})
10
- allow(cli).to receive(:httpclient).and_return(httpclient)
11
- cli
12
- end
13
9
  let(:res){ double(:res, status: 200, body: {}.to_json) }
14
10
 
15
11
  let(:cmd){ Magellan::Cli::Resources::Project.new }
16
12
 
17
13
  before do
18
- allow(cmd).to receive(:access_api).and_yield(cli)
14
+ allow(cmd.http_conn).to receive(:httpclient).and_return(httpclient)
15
+ allow(cmd.http_conn).to receive(:check_login_auth!)
16
+ allow(cmd.http_conn).to receive(:login_auth).and_return({})
19
17
  end
20
18
 
21
19
  describe :list do
22
20
  it do
23
- expect(httpclient).to receive(:get).with(%r{\A#{base_url}/admin/project.json}).and_return(res)
21
+ expect(httpclient).to receive(:get).with(%{#{base_url}/admin/project.json}).and_return(res)
24
22
  expect($stdout).to receive(:puts)
25
23
  cmd.list
26
24
  end
@@ -5,8 +5,8 @@ describe Magellan::Cli::Resources::Team do
5
5
 
6
6
  let(:cmd){ Magellan::Cli::Resources::Team.new }
7
7
 
8
- let(:cli){ double(:cli, :check_login_auth! => nil) }
9
- before{ allow(cmd).to receive(:cli).and_return(cli) }
8
+ let(:http_conn){ double(:http_conn, :check_login_auth! => nil) }
9
+ before{ allow(cmd).to receive(:http_conn).and_return(http_conn) }
10
10
 
11
11
  describe :list do
12
12
  before do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magellan-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.9
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - akm2000
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-18 00:00:00.000000000 Z
11
+ date: 2015-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
@@ -120,14 +120,14 @@ dependencies:
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: 0.2.2
123
+ version: 0.2.4
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: 0.2.2
130
+ version: 0.2.4
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: bundler
133
133
  requirement: !ruby/object:Gem::Requirement
@@ -199,7 +199,6 @@ files:
199
199
  - lib/magellan/cli/i18n.rb
200
200
  - lib/magellan/cli/locales/en.yml
201
201
  - lib/magellan/cli/locales/ja.yml
202
- - lib/magellan/cli/login.rb
203
202
  - lib/magellan/cli/messaging.rb
204
203
  - lib/magellan/cli/messaging/base.rb
205
204
  - lib/magellan/cli/messaging/http.rb
@@ -246,6 +245,7 @@ files:
246
245
  - spec/magellan/cli/Magellan.yml
247
246
  - spec/magellan/cli/command_spec.rb
248
247
  - spec/magellan/cli/file_access_spec.rb
248
+ - spec/magellan/cli/http_spec.rb
249
249
  - spec/magellan/cli/login_page.html
250
250
  - spec/magellan/cli/login_spec.rb
251
251
  - spec/magellan/cli/messaging/http_body.json
@@ -292,6 +292,7 @@ test_files:
292
292
  - spec/magellan/cli/Magellan.yml
293
293
  - spec/magellan/cli/command_spec.rb
294
294
  - spec/magellan/cli/file_access_spec.rb
295
+ - spec/magellan/cli/http_spec.rb
295
296
  - spec/magellan/cli/login_page.html
296
297
  - spec/magellan/cli/login_spec.rb
297
298
  - spec/magellan/cli/messaging/http_body.json
@@ -1,119 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require "magellan/cli"
3
-
4
- require 'httpclient'
5
- require 'json'
6
- require 'uri'
7
- require 'nokogiri'
8
-
9
- require 'active_support/core_ext/hash/keys'
10
-
11
- module Magellan
12
- module Cli
13
- class Login
14
- include Magellan::Cli::FileAccess
15
-
16
- PRODUCTION_HTTP_PORT = 80
17
- PRODUCTION_HTTPS_PORT = 443
18
-
19
- DEFAULT_HTTP_PORT = (ENV['DEFAULT_HTTP_PORT' ] || 80).to_i
20
- DEFAULT_HTTPS_PORT = (ENV['DEFAULT_HTTPS_PORT'] || 443).to_i
21
-
22
- attr_reader :httpclient
23
- attr_reader :base_url
24
-
25
- attr_reader :auth_token
26
- attr_reader :login_auth
27
-
28
- # Magellan::Cli::Loginのコンストラクタです。
29
- #
30
- # @param [String] base_url_or_host 接続先の基準となるURLあるいはホスト名
31
- # @param [Hash] options オプション
32
- # @option options [String] :api_version APIのバージョン。デフォルトは "1.0.0"
33
- def initialize(base_url_or_host = nil, options = {})
34
- base_url_or_host ||= (ENV["MAGELLAN_SITE"] || "https://api-asia.magellanic-clouds.com")
35
- if base_url_or_host =~ URI.regexp
36
- @base_url = base_url_or_host.sub(/\/\Z/, '')
37
- uri = URI.parse(@base_url)
38
- else
39
- if config_path = search_file(".magellan-cli.yml")
40
- config = YAML.load_file_with_erb(config_path)
41
- options = config[base_url_or_host.to_s].deep_symbolize_keys.update(options)
42
- end
43
- uri = URI::Generic.build({scheme: "http", host: base_url_or_host, port: DEFAULT_HTTP_PORT}.update(options))
44
- @base_url = uri.to_s
45
- end
46
-
47
- @httpclient = HTTPClient.new
48
- @httpclient.ssl_config.verify_mode = nil # 自己署名の証明書をOKにする
49
- @login_auth = load_selections["login"]
50
- end
51
-
52
- def login_form_url
53
- @login_form_url ||= base_url + "/users/sign_in.html"
54
- end
55
- def login_url
56
- @login_url ||= base_url + "/api/sign_in.json"
57
- end
58
-
59
- def check_login_auth!
60
- auth = login_auth
61
- if auth.nil? || auth.empty?
62
- raise Magellan::Cli::Error, I18n.t(:not_logged_in, scope: [:login, :check_login_auth], command: File.basename($0))
63
- end
64
- end
65
-
66
- # magellan-apiサーバに接続してログインの検証とアクセストークンの保存を行います。
67
- #
68
- # @return [boolean] login成功/失敗
69
- def api_login!(email, password)
70
- @auth_token ||= get_auth_token
71
- params = {
72
- "user" => {
73
- "email" => email,
74
- "password" => password
75
- },
76
- "authenticity_token" => @auth_token
77
- }.to_json
78
- res2 = Ssl.retry_on_ssl_error("login"){ @httpclient.post(login_url, params, JSON_HEADER) }
79
-
80
- case res2.status
81
- when 200...300 then logined = true
82
- else logined = false
83
- end
84
-
85
- if logined
86
- body = JSON.parse res2.body
87
- update_selections("login" => {"email" => email, "token" => body["token"] })
88
- else
89
- update_selections("login" => nil)
90
- end
91
- logined
92
- end
93
-
94
- def get_auth_token
95
- res = Ssl.retry_on_ssl_error("login_form"){ @httpclient.get(login_form_url) }
96
- doc = Nokogiri::HTML.parse(res.body, login_form_url, res.body_encoding.to_s)
97
- node = doc.xpath('//input[@name="authenticity_token"]').first
98
- unless node
99
- raise Cli::Error.new("fail to login Magellan")
100
- end
101
- node.attribute('value').value
102
- end
103
-
104
- # @httpclient.inspectの戻り値の文字列が巨大なので、inspectで出力しないようにします。
105
- def inspect
106
- r = "#<#{self.class.name}:#{self.object_id} "
107
- fields = (instance_variables - [:@httpclient]).map{|f| "#{f}=#{instance_variable_get(f).inspect}"}
108
- r << fields.join(", ") << ">"
109
- end
110
-
111
- def search_file(basename)
112
- dirs = [".", "./config", ENV['HOME']].join(",")
113
- Dir["{#{dirs}}/#{basename}"].select{|path| File.readable?(path)}.first
114
- end
115
- private :search_file
116
-
117
- end
118
- end
119
- end