shopify-cli 1.14.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/CONTRIBUTING.md +7 -7
  4. data/.github/DESIGN.md +3 -3
  5. data/.github/workflows/build.yml +1 -1
  6. data/.gitignore +3 -0
  7. data/.rubocop.yml +3 -1
  8. data/.ruby-version +1 -1
  9. data/CHANGELOG.md +35 -29
  10. data/Gemfile +4 -0
  11. data/Gemfile.lock +32 -0
  12. data/LICENSE +4 -1
  13. data/README.md +92 -26
  14. data/RELEASING.md +29 -7
  15. data/Rakefile +2 -2
  16. data/SECURITY.md +1 -1
  17. data/bin/load_shopify.rb +1 -1
  18. data/bin/shopify +3 -3
  19. data/dev.yml +1 -1
  20. data/docs/app/node/index.md +1 -1
  21. data/docs/app/rails/index.md +1 -1
  22. data/docs/core/index.md +1 -1
  23. data/docs/getting-started/index.md +1 -1
  24. data/docs/getting-started/install/index.md +1 -1
  25. data/docs/getting-started/migrate/index.md +1 -1
  26. data/docs/getting-started/uninstall/index.md +1 -1
  27. data/docs/getting-started/upgrade/index.md +1 -1
  28. data/docs/help/start-app/index.md +1 -1
  29. data/docs/index.md +1 -1
  30. data/ext/shopify-cli/extconf.rb +17 -5
  31. data/install.sh +1 -1
  32. data/lib/docgen/index_template.md.erb +2 -2
  33. data/lib/graphql/all_orgs_with_extensions.graphql +37 -0
  34. data/lib/graphql/find_organization.graphql +2 -1
  35. data/lib/project_types/extension/cli.rb +18 -15
  36. data/lib/project_types/extension/commands/build.rb +4 -5
  37. data/lib/project_types/extension/commands/connect.rb +35 -0
  38. data/lib/project_types/extension/commands/create.rb +12 -16
  39. data/lib/project_types/extension/commands/extension_command.rb +2 -2
  40. data/lib/project_types/extension/commands/info.rb +86 -0
  41. data/lib/project_types/extension/commands/push.rb +8 -7
  42. data/lib/project_types/extension/commands/register.rb +4 -5
  43. data/lib/project_types/extension/commands/serve.rb +5 -8
  44. data/lib/project_types/extension/commands/tunnel.rb +3 -1
  45. data/lib/project_types/extension/errors.rb +9 -0
  46. data/lib/project_types/extension/extension_project.rb +5 -0
  47. data/lib/project_types/extension/features/argo.rb +6 -6
  48. data/lib/project_types/extension/features/argo_runtime.rb +22 -66
  49. data/lib/project_types/extension/features/argo_serve.rb +25 -18
  50. data/lib/project_types/extension/forms/connect.rb +42 -0
  51. data/lib/project_types/extension/forms/questions/ask_name.rb +14 -6
  52. data/lib/project_types/extension/forms/questions/ask_registration.rb +51 -0
  53. data/lib/project_types/extension/messages/messages.rb +75 -11
  54. data/lib/project_types/extension/models/specification.rb +1 -0
  55. data/lib/project_types/extension/models/specification_handlers/{checkout_argo_extension.rb → checkout_ui_extension.rb} +3 -1
  56. data/lib/project_types/extension/models/specification_handlers/default.rb +13 -3
  57. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +86 -0
  58. data/lib/project_types/extension/models/specifications.rb +1 -0
  59. data/lib/project_types/extension/tasks/configure_features.rb +6 -7
  60. data/lib/project_types/extension/tasks/configure_options.rb +20 -0
  61. data/lib/project_types/extension/tasks/get_extensions.rb +32 -0
  62. data/lib/project_types/node/cli.rb +9 -21
  63. data/lib/project_types/node/commands/connect.rb +8 -2
  64. data/lib/project_types/node/commands/create.rb +9 -5
  65. data/lib/project_types/node/commands/deploy.rb +15 -5
  66. data/lib/project_types/node/commands/deploy/heroku.rb +29 -29
  67. data/lib/project_types/node/commands/generate.rb +4 -2
  68. data/lib/project_types/node/commands/open.rb +4 -2
  69. data/lib/project_types/node/commands/serve.rb +3 -2
  70. data/lib/project_types/node/commands/tunnel.rb +4 -2
  71. data/lib/project_types/node/messages/messages.rb +46 -89
  72. data/lib/project_types/rails/cli.rb +9 -21
  73. data/lib/project_types/rails/commands/connect.rb +8 -2
  74. data/lib/project_types/rails/commands/create.rb +10 -6
  75. data/lib/project_types/rails/commands/deploy.rb +15 -5
  76. data/lib/project_types/rails/commands/deploy/heroku.rb +84 -82
  77. data/lib/project_types/rails/commands/generate.rb +15 -5
  78. data/lib/project_types/rails/commands/generate/webhook.rb +28 -26
  79. data/lib/project_types/rails/commands/open.rb +4 -2
  80. data/lib/project_types/rails/commands/serve.rb +3 -2
  81. data/lib/project_types/rails/commands/tunnel.rb +4 -2
  82. data/lib/project_types/rails/messages/messages.rb +54 -101
  83. data/lib/project_types/script/cli.rb +5 -7
  84. data/lib/project_types/script/commands/create.rb +3 -1
  85. data/lib/project_types/script/commands/push.rb +4 -2
  86. data/lib/project_types/script/messages/messages.rb +52 -45
  87. data/lib/project_types/script/ui/error_handler.rb +2 -2
  88. data/lib/project_types/theme/cli.rb +15 -27
  89. data/lib/project_types/theme/commands/check.rb +33 -0
  90. data/lib/project_types/theme/commands/delete.rb +64 -0
  91. data/lib/project_types/theme/commands/language_server.rb +16 -0
  92. data/lib/project_types/theme/commands/package.rb +55 -0
  93. data/lib/project_types/theme/commands/publish.rb +43 -0
  94. data/lib/project_types/theme/commands/pull.rb +51 -0
  95. data/lib/project_types/theme/commands/push.rb +58 -32
  96. data/lib/project_types/theme/commands/serve.rb +7 -17
  97. data/lib/project_types/theme/forms/confirm_store.rb +15 -0
  98. data/lib/project_types/theme/forms/select.rb +59 -0
  99. data/lib/project_types/theme/messages/messages.rb +110 -106
  100. data/lib/project_types/theme/ui/sync_progress_bar.rb +20 -0
  101. data/lib/shopify-cli/admin_api.rb +53 -38
  102. data/lib/shopify-cli/admin_api/populate_resource_command.rb +6 -14
  103. data/lib/shopify-cli/admin_api/schema.rb +1 -10
  104. data/lib/shopify-cli/api.rb +29 -14
  105. data/lib/shopify-cli/command.rb +15 -3
  106. data/lib/shopify-cli/commands.rb +7 -2
  107. data/lib/shopify-cli/commands/help.rb +2 -29
  108. data/lib/shopify-cli/commands/login.rb +95 -0
  109. data/lib/shopify-cli/commands/logout.rb +24 -8
  110. data/lib/shopify-cli/commands/populate.rb +23 -0
  111. data/lib/{project_types/node → shopify-cli}/commands/populate/customer.rb +2 -8
  112. data/lib/{project_types/node → shopify-cli}/commands/populate/draft_order.rb +2 -2
  113. data/lib/{project_types/node → shopify-cli}/commands/populate/product.rb +2 -8
  114. data/lib/shopify-cli/commands/store.rb +15 -0
  115. data/lib/shopify-cli/commands/switch.rb +39 -0
  116. data/lib/shopify-cli/commands/system.rb +12 -0
  117. data/lib/shopify-cli/commands/whoami.rb +28 -0
  118. data/lib/shopify-cli/connect.rb +32 -0
  119. data/lib/shopify-cli/context.rb +52 -4
  120. data/lib/shopify-cli/core/entry_point.rb +3 -22
  121. data/lib/shopify-cli/db.rb +4 -4
  122. data/lib/shopify-cli/http_request.rb +10 -0
  123. data/lib/shopify-cli/identity_auth.rb +282 -0
  124. data/lib/shopify-cli/{oauth → identity_auth}/servlet.rb +11 -12
  125. data/lib/shopify-cli/messages/messages.rb +132 -39
  126. data/lib/shopify-cli/partners_api.rb +21 -44
  127. data/lib/shopify-cli/partners_api/organizations.rb +8 -0
  128. data/lib/shopify-cli/project_commands.rb +16 -0
  129. data/lib/shopify-cli/project_type.rb +0 -31
  130. data/lib/shopify-cli/shopifolk.rb +8 -11
  131. data/lib/shopify-cli/sub_command.rb +1 -0
  132. data/lib/shopify-cli/tasks.rb +3 -0
  133. data/lib/shopify-cli/tasks/confirm_store.rb +18 -0
  134. data/lib/shopify-cli/tasks/create_api_client.rb +2 -2
  135. data/lib/shopify-cli/tasks/ensure_authenticated.rb +13 -0
  136. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +1 -1
  137. data/lib/shopify-cli/tasks/ensure_project_type.rb +12 -0
  138. data/lib/shopify-cli/tasks/select_org_and_shop.rb +0 -3
  139. data/lib/shopify-cli/theme/dev_server.rb +98 -0
  140. data/lib/shopify-cli/theme/dev_server/certificate_manager.rb +79 -0
  141. data/lib/shopify-cli/theme/dev_server/header_hash.rb +94 -0
  142. data/lib/shopify-cli/theme/dev_server/hot-reload.js +93 -0
  143. data/lib/shopify-cli/theme/dev_server/hot_reload.rb +76 -0
  144. data/lib/shopify-cli/theme/dev_server/local_assets.rb +87 -0
  145. data/lib/shopify-cli/theme/dev_server/proxy.rb +205 -0
  146. data/lib/shopify-cli/theme/dev_server/sse.rb +75 -0
  147. data/lib/shopify-cli/theme/dev_server/watcher.rb +59 -0
  148. data/lib/shopify-cli/theme/dev_server/web_server.rb +140 -0
  149. data/lib/shopify-cli/theme/development_theme.rb +69 -0
  150. data/lib/shopify-cli/theme/file.rb +112 -0
  151. data/lib/shopify-cli/theme/ignore_filter.rb +109 -0
  152. data/lib/shopify-cli/theme/mime_type.rb +34 -0
  153. data/lib/shopify-cli/theme/syncer.rb +328 -0
  154. data/lib/shopify-cli/theme/theme.rb +204 -0
  155. data/lib/shopify-cli/version.rb +1 -1
  156. data/lib/shopify_cli.rb +18 -11
  157. data/shopify-cli.gemspec +12 -5
  158. data/shopify.fish +1 -1
  159. data/shopify.sh +1 -1
  160. metadata +88 -34
  161. data/.github/workflows/release.yml +0 -59
  162. data/lib/project_types/extension/features/argo_serve_options.rb +0 -42
  163. data/lib/project_types/node/commands/populate.rb +0 -23
  164. data/lib/project_types/rails/commands/populate.rb +0 -23
  165. data/lib/project_types/rails/commands/populate/customer.rb +0 -31
  166. data/lib/project_types/rails/commands/populate/draft_order.rb +0 -28
  167. data/lib/project_types/rails/commands/populate/product.rb +0 -30
  168. data/lib/project_types/theme/commands/connect.rb +0 -54
  169. data/lib/project_types/theme/commands/create.rb +0 -48
  170. data/lib/project_types/theme/commands/deploy.rb +0 -38
  171. data/lib/project_types/theme/commands/generate.rb +0 -20
  172. data/lib/project_types/theme/commands/generate/env.rb +0 -79
  173. data/lib/project_types/theme/forms/connect.rb +0 -34
  174. data/lib/project_types/theme/forms/create.rb +0 -22
  175. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +0 -78
  176. data/lib/project_types/theme/themekit.rb +0 -113
  177. data/lib/shopify-cli/commands/connect.rb +0 -64
  178. data/lib/shopify-cli/commands/create.rb +0 -50
  179. data/lib/shopify-cli/oauth.rb +0 -198
@@ -1,5 +1,5 @@
1
1
  module ShopifyCli
2
- class OAuth
2
+ class IdentityAuth
3
3
  class Servlet < WEBrick::HTTPServlet::AbstractServlet
4
4
  TEMPLATE = %{<!DOCTYPE html>
5
5
  <html>
@@ -13,15 +13,13 @@ module ShopifyCli
13
13
  </html>
14
14
  }
15
15
  AUTOCLOSE_TEMPLATE = %{
16
- <script>
17
- setTimeout(function() { window.close(); }, 3000)
18
- </script>
16
+ <script>window.close();</script>
19
17
  }
20
18
 
21
- def initialize(server, oauth, token)
19
+ def initialize(server, identity_auth, token)
22
20
  super
23
21
  @server = server
24
- @oauth = oauth
22
+ @identity_auth = identity_auth
25
23
  @state_token = token
26
24
  end
27
25
 
@@ -30,16 +28,16 @@ module ShopifyCli
30
28
  respond_with(
31
29
  res,
32
30
  400,
33
- Context.message("core.oauth.servlet.invalid_request_response", req.query["error_description"])
31
+ Context.message("core.identity_auth.servlet.invalid_request_response", req.query["error_description"])
34
32
  )
35
33
  elsif req.query["state"] != @state_token
36
- response_message = Context.message("core.oauth.servlet.invalid_state_response")
34
+ response_message = Context.message("core.identity_auth.servlet.invalid_state_response")
37
35
  req.query.merge!("error" => "invalid_state", "error_description" => response_message)
38
36
  respond_with(res, 403, response_message)
39
37
  else
40
- respond_with(res, 200, Context.message("core.oauth.servlet.success_response"))
38
+ respond_with(res, 200, Context.message("core.identity_auth.servlet.success_response"))
41
39
  end
42
- @oauth.response_query = req.query
40
+ @identity_auth.response_query = req.query
43
41
  @server.shutdown
44
42
  end
45
43
 
@@ -49,8 +47,9 @@ module ShopifyCli
49
47
  status: status,
50
48
  message: message,
51
49
  color: successful ? "black" : "red",
52
- title:
53
- Context.message(successful ? "core.oauth.servlet.authenticated" : "core.oauth.servlet.not_authenticated"),
50
+ title: Context.message(
51
+ successful ? "core.identity_auth.servlet.authenticated" : "core.identity_auth.servlet.not_authenticated"
52
+ ),
54
53
  autoclose: successful ? AUTOCLOSE_TEMPLATE : "",
55
54
  }
56
55
  response.status = status
@@ -7,19 +7,14 @@ module ShopifyCli
7
7
  create: {
8
8
  info: {
9
9
  created: "{{v}} {{green:%s}} was created in the organization's Partner Dashboard {{underline:%s}}",
10
- serve: "{{*}} Change directories to your new project folder {{green:%s}} and run {{command:%s serve}} " \
11
- "to start a local server",
10
+ serve: "{{*}} Change directories to your new project folder {{green:%s}} and run "\
11
+ "{{command:%s %s serve}} to start a local server",
12
12
  install: "{{*}} Then, visit {{underline:%s/test}} to install {{green:%s}} on your Dev Store",
13
13
  },
14
14
  },
15
15
  },
16
16
  core: {
17
17
  connect: {
18
- help: <<~HELP,
19
- Connect (or re-connect) an existing project to a Shopify partner organization and/or a store. Creates or updates the {{green:.env}} file, and creates the {{green:.shopify-cli.yml}} file.
20
- Usage: {{command:%s connect}}
21
- HELP
22
-
23
18
  already_connected_warning: "{{yellow:! This app appears to be already connected}}",
24
19
  project_type_select: "What type of project would you like to connect?",
25
20
  cli_yml_saved: ".shopify-cli.yml saved to project root",
@@ -32,19 +27,6 @@ module ShopifyCli
32
27
  OPEN
33
28
  },
34
29
 
35
- create: {
36
- help: <<~HELP,
37
- Create a new project.
38
- Usage: {{command:%s create [ %s ]}}
39
- HELP
40
-
41
- error: {
42
- invalid_app_type: "{{red:Error}}: invalid app type {{bold:%s}}",
43
- },
44
-
45
- project_type_select: "What type of project would you like to create?",
46
- },
47
-
48
30
  env_file: {
49
31
  saving_header: "writing %s file...",
50
32
  saving: "writing %s file",
@@ -99,8 +81,6 @@ module ShopifyCli
99
81
  preamble: <<~MESSAGE,
100
82
  Use {{command:%s help <command>}} to display detailed information about a specific command.
101
83
 
102
- {{bold:Available core commands:}}
103
-
104
84
  MESSAGE
105
85
  },
106
86
 
@@ -129,13 +109,35 @@ module ShopifyCli
129
109
  npm_installed_deps: "%d npm dependencies installed",
130
110
  },
131
111
 
112
+ login: {
113
+ help: <<~HELP,
114
+ Log in to the Shopify CLI by authenticating with a store or partner organization
115
+ Usage: {{command:%s login [--store=STORE]}}
116
+ HELP
117
+ invalid_shop: <<~MESSAGE,
118
+ Invalid store provided (%s). Please provide the store in the following format: my-store.myshopify.com
119
+ MESSAGE
120
+ shop_prompt: <<~PROMPT,
121
+ What store are you connecting to? (e.g. my-store.myshopify.com; do {{bold:NOT}} include protocol part, e.g., https://)
122
+ PROMPT
123
+ },
124
+
132
125
  logout: {
133
126
  help: <<~HELP,
134
- Log out of a currently authenticated partner organization and store, or clear invalid credentials
127
+ Log out of an authenticated partner organization and store, or clear invalid credentials
135
128
  Usage: {{command:%s logout}}
136
129
  HELP
137
130
 
138
- success: "Logged out of partner organization and store",
131
+ success: "Successfully logged out of your account",
132
+ },
133
+
134
+ switch: {
135
+ help: <<~HELP,
136
+ Switch between development stores in your partner organization
137
+ Usage: {{command:%s switch [--store=STORE]}}
138
+ HELP
139
+ disabled_as_shopify_org: "Can't switch development stores logged in as {{green:Shopify partners org}}",
140
+ success: "Switched development store to {{green:%s}}",
139
141
  },
140
142
 
141
143
  monorail: {
@@ -146,9 +148,12 @@ module ShopifyCli
146
148
  MSG
147
149
  },
148
150
 
149
- oauth: {
151
+ identity_auth: {
150
152
  error: {
151
153
  timeout: "Timed out while waiting for response from Shopify",
154
+ local_identity_not_running: "Identity needs to be running locally in order to proceed.",
155
+ reauthenticate: "Please login again with {{command:shopify login}}",
156
+ invalid_destination: "The store %s doesn't exist. Please log out and try again.",
152
157
  },
153
158
 
154
159
  location: {
@@ -166,6 +171,7 @@ module ShopifyCli
166
171
  authenticated: "Authenticated successfully",
167
172
  not_authenticated: "Failed to authenticate",
168
173
  },
174
+ login_prompt: "Please ensure you've logged in with {{command:%s login}} and try again",
169
175
  },
170
176
 
171
177
  options: {
@@ -185,6 +191,10 @@ module ShopifyCli
185
191
  api: {
186
192
  error: {
187
193
  failed_auth: "Failed to authenticate with Shopify. Please try again later.",
194
+ failed_auth_debugging: "{{red:Please provide this information with your report:}}\n%s\n\n",
195
+ forbidden: <<~FORBIDDEN,
196
+ Command not allowed with current login. Please check your login details with {{command:%s whoami}}. You may need to request additional permissions for this action.
197
+ FORBIDDEN
188
198
  internal_server_error: "{{red:{{x}} An unexpected error occurred on Shopify.}}",
189
199
  internal_server_error_debug: "\n{{red:Response details:}}\n%s\n\n",
190
200
  invalid_url: "Invalid URL: %s",
@@ -192,22 +202,78 @@ module ShopifyCli
192
202
  },
193
203
 
194
204
  populate: {
205
+ help: <<~HELP,
206
+ Populate a Shopify store with example customers, orders, or products.
207
+ Usage: {{command:%s populate [ customers | draftorders | products ]}}
208
+ HELP
209
+
210
+ extended_help: <<~HELP,
211
+ {{bold:Subcommands:}}
212
+
213
+ {{cyan:customers [options]}}: Add dummy customers to the specified store.
214
+ Usage: {{command:%1$s populate customers}}
215
+
216
+ {{cyan:draftorders [options]}}: Add dummy orders to the specified store.
217
+ Usage: {{command:%1$s populate draftorders}}
218
+
219
+ {{cyan:products [options]}}: Add dummy products to the specified store.
220
+ Usage: {{command:%1$s populate products}}
221
+
222
+ {{bold:Options:}}
223
+
224
+ {{cyan:--count [integer]}}: The number of dummy items to populate. Defaults to 5.
225
+ {{cyan:--silent}}: Silence the populate output.
226
+ {{cyan:--help}}: Display more options specific to each subcommand.
227
+
228
+ {{bold:Examples:}}
229
+
230
+ {{command:%1$s populate products}}
231
+ Populate your store with 5 additional products.
232
+
233
+ {{command:%1$s populate customers --count 30}}
234
+ Populate your store with 30 additional customers.
235
+
236
+ {{command:%1$s populate draftorders}}
237
+ Populate your store with 5 additional orders.
238
+
239
+ {{command:%1$s populate products --help}}
240
+ Display the list of options available to customize the {{command:%1$s populate products}} command.
241
+ HELP
242
+
243
+ error: {
244
+ no_shop: "No store found. Please run {{command:%s login --store=STORE}} to login to a specific store",
245
+ },
246
+
247
+ customer: {
248
+ added: "%s added to {{green:%s}} at {{underline:%scustomers/%d}}",
249
+ },
250
+
251
+ draft_order: {
252
+ added: "DraftOrder added to {{green:%s}} at {{underline:%sdraft_orders/%d}}",
253
+ },
254
+
195
255
  options: {
196
256
  header: "{{bold:{{cyan:%s}} options:}}",
197
257
  count_help: "Number of resources to generate",
198
258
  },
259
+
199
260
  populating: "Populating %d %ss...",
261
+
200
262
  completion_message: <<~COMPLETION_MESSAGE,
201
263
  Successfully added %d %s to {{green:%s}}
202
264
  {{*}} View all %ss at {{underline:%s%ss}}
203
265
  COMPLETION_MESSAGE
266
+
267
+ product: {
268
+ added: "%s added to {{green:%s}} at {{underline:%sproducts/%d}}",
269
+ },
204
270
  },
205
271
 
206
272
  project: {
207
273
  error: {
208
274
  not_in_project: <<~MESSAGE,
209
275
  {{x}} You are not in a Shopify app project
210
- {{yellow:{{*}}}}{{reset: Run}}{{cyan: shopify create}}{{reset: to create your app}}
276
+ {{yellow:{{*}}}}{{reset: Run}}{{cyan: shopify rails create}}{{reset: or}}{{cyan: shopify node create}}{{reset: to create your app}}
211
277
  MESSAGE
212
278
  },
213
279
  },
@@ -239,7 +305,8 @@ module ShopifyCli
239
305
  unknown_option: "{{x}} {{red:unknown option '%s'}}",
240
306
  },
241
307
 
242
- header: "{{bold:Shopify App CLI}}",
308
+ header: "{{bold:Shopify CLI}}",
309
+ shop_header: "{{bold:Current Shop}}",
243
310
  const: "%17s = %s",
244
311
  ruby_header: <<~RUBY_MESSAGE,
245
312
  {{bold:Ruby (via RbConfig)}}
@@ -266,7 +333,20 @@ module ShopifyCli
266
333
  identity_is_shopifolk: "{{v}} Checked user settings: you’re Shopify staff!",
267
334
  },
268
335
 
336
+ store: {
337
+ help: <<~HELP,
338
+ Display current store.
339
+ Usage: {{command:%s store}}
340
+ HELP
341
+ shop: "You're currently logged into {{green:%s}}",
342
+ },
343
+
269
344
  tasks: {
345
+ confirm_store: {
346
+ prompt: "You are currently logged into {{green:%s}}. Do you want to proceed using this store?",
347
+ confirmation: "Proceeding using {{green:%s}}",
348
+ cancelling: "Cancelling ...",
349
+ },
270
350
  ensure_env: {
271
351
  organization_select: "To which partner organization does this project belong?",
272
352
  no_development_stores: <<~MESSAGE,
@@ -293,6 +373,9 @@ module ShopifyCli
293
373
  MESSAGE
294
374
  transfer_disabled: "{{v}} Transfer has been disabled on %s.",
295
375
  },
376
+ ensure_project_type: {
377
+ wrong_project_type: "This command can only be run within %s projects.",
378
+ },
296
379
  update_dashboard_urls: {
297
380
  updated: "{{v}} Whitelist URLS updated in Partners Dashboard}}",
298
381
  update_error:
@@ -310,10 +393,11 @@ module ShopifyCli
310
393
  organization_not_found: "Cannot find a partner organization with that ID",
311
394
  shopifolk_notice: <<~MESSAGE,
312
395
  {{i}} As a {{green:Shopify}} employee, the authentication should take you to the Shopify Okta login,
313
- NOT the Partner account login. Please run {{command:%s logout}} and try again.
396
+ NOT the partner account login. Please run {{command:%s logout}} and try again.
314
397
  MESSAGE
315
398
  },
316
- first_party: "Are you working on a 1P (1st Party) app?",
399
+ first_party: "Are you working on a {{green:Shopify project}} on behalf of the"\
400
+ " {{green:Shopify partners org}}?",
317
401
  identified_as_shopify: "We've identified you as a {{green:Shopify}} employee.",
318
402
  organization: "Partner organization {{green:%s (%s)}}",
319
403
  organization_select: "Select partner organization",
@@ -334,7 +418,7 @@ module ShopifyCli
334
418
  signup_suggestion: <<~MESSAGE,
335
419
  {{*}} To avoid tunnels that timeout, it is recommended to signup for a free ngrok
336
420
  account at {{underline:https://ngrok.com/signup}}. After you signup, install your
337
- personalized authorization token using {{command:%s tunnel auth <token>}}.
421
+ personalized authorization token using {{command:%s [ node | rails ] tunnel auth <token>}}.
338
422
  MESSAGE
339
423
  start: "{{v}} ngrok tunnel running at {{underline:%s}}",
340
424
  start_with_account: "{{v}} ngrok tunnel running at {{underline:%s}}, with account %s",
@@ -358,21 +442,30 @@ module ShopifyCli
358
442
 
359
443
  DEVELOPMENT
360
444
 
361
- shell_shim: <<~MESSAGE,
362
- {{x}} This version of Shopify App CLI is no longer supported. You’ll need to migrate to the new CLI version to continue.
445
+ new_version: <<~MESSAGE,
446
+ {{*}} {{yellow:A new version of Shopify CLI is available! You have version %s and the latest version is %s.
363
447
 
364
- Please visit this page for complete instructions:
365
- {{underline:https://shopify.dev/tools/cli/troubleshooting#migrate-from-a-legacy-version}}
448
+ To upgrade, follow the instructions for the package manager you’re using:
449
+ {{underline:https://shopify.dev/tools/cli/troubleshooting#upgrade-shopify-cli}}}}
366
450
 
367
451
  MESSAGE
452
+ },
368
453
 
369
- new_version: <<~MESSAGE,
370
- {{*}} {{yellow:A new version of Shopify App CLI is available! You have version %s and the latest version is %s.
371
-
372
- To upgrade, follow the instructions for the package manager you’re using:
373
- {{underline:https://shopify.dev/tools/cli/troubleshooting#upgrade-shopify-app-cli}}}}
454
+ whoami: {
455
+ help: <<~HELP,
456
+ Identifies which partner organization or store you are currently logged into.
457
+ Usage: {{command:%s whoami}}
458
+ HELP
459
+ not_logged_in: <<~MESSAGE,
460
+ It doesn't appear that you're logged in. You must log into a partner organization or a store staff account.
374
461
 
462
+ If trying to log into a store staff account, please use {{command:%s login --store=STORE}} to log in.
463
+ MESSAGE
464
+ logged_in_shop_only: <<~MESSAGE,
465
+ Logged into store {{green:%s}} as staff (no partner organizations available for this login)
375
466
  MESSAGE
467
+ logged_in_partner_only: "Logged into partner organization {{green:%s}}",
468
+ logged_in_partner_and_shop: "Logged into store {{green:%s}} in partner organization {{green:%s}}",
376
469
  },
377
470
  },
378
471
  }.freeze
@@ -45,9 +45,18 @@ module ShopifyCli
45
45
  # ShopifyCli::PartnersAPI.query(@ctx, 'all_organizations')
46
46
  #
47
47
  def query(ctx, query_name, **variables)
48
- authenticated_req(ctx) do
48
+ CLI::Kit::Util.begin do
49
49
  api_client(ctx).query(query_name, variables: variables)
50
+ end.retry_after(API::APIRequestUnauthorizedError, retries: 1) do
51
+ ShopifyCli::IdentityAuth.new(ctx: ctx).reauthenticate
50
52
  end
53
+ rescue API::APIRequestUnauthorizedError => e
54
+ if (request_info = auth_failure_info(ctx, e))
55
+ ctx.puts(ctx.message("core.api.error.failed_auth_debugging", request_info))
56
+ end
57
+ ctx.abort(ctx.message("core.api.error.failed_auth"))
58
+ rescue API::APIRequestNotFoundError
59
+ ctx.puts(ctx.message("core.partners_api.error.account_not_found", ShopifyCli::TOOL_NAME))
51
60
  end
52
61
 
53
62
  def partners_url_for(organization_id, api_client_id, local_debug)
@@ -59,18 +68,6 @@ module ShopifyCli
59
68
 
60
69
  private
61
70
 
62
- def authenticated_req(ctx, &block)
63
- CLI::Kit::Util
64
- .begin(&block)
65
- .retry_after(API::APIRequestUnauthorizedError, retries: 1) do
66
- authenticate(ctx)
67
- end
68
- rescue API::APIRequestUnauthorizedError
69
- ctx.abort(ctx.message("core.api.error.failed_auth"))
70
- rescue API::APIRequestNotFoundError
71
- ctx.puts(ctx.message("core.partners_api.error.account_not_found", ShopifyCli::TOOL_NAME))
72
- end
73
-
74
71
  def api_client(ctx)
75
72
  new(
76
73
  ctx: ctx,
@@ -80,37 +77,12 @@ module ShopifyCli
80
77
  end
81
78
 
82
79
  def access_token(ctx)
83
- ShopifyCli::DB.get(:identity_exchange_token) do
84
- authenticate(ctx)
85
- ShopifyCli::DB.get(:identity_exchange_token)
80
+ ShopifyCli::DB.get(:partners_exchange_token) do
81
+ IdentityAuth.new(ctx: ctx).authenticate
82
+ ShopifyCli::DB.get(:partners_exchange_token)
86
83
  end
87
84
  end
88
85
 
89
- def authenticate(ctx)
90
- OAuth.new(
91
- ctx: ctx,
92
- service: "identity",
93
- client_id: cli_id,
94
- scopes: scopes.join(" "),
95
- request_exchange: partners_id,
96
- ).authenticate("#{auth_endpoint}/oauth")
97
- end
98
-
99
- def partners_id
100
- return "271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6" if ENV[LOCAL_DEBUG].nil?
101
- "df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978"
102
- end
103
-
104
- def cli_id
105
- return "fbdb2649-e327-4907-8f67-908d24cfd7e3" if ENV[LOCAL_DEBUG].nil?
106
- "e5380e02-312a-7408-5718-e07017e9cf52"
107
- end
108
-
109
- def auth_endpoint
110
- return "https://accounts.shopify.com" if ENV[LOCAL_DEBUG].nil?
111
- "https://identity.myshopify.io"
112
- end
113
-
114
86
  def endpoint
115
87
  return "https://partners.shopify.com" if ENV[LOCAL_DEBUG].nil?
116
88
  "https://partners.myshopify.io/"
@@ -125,10 +97,15 @@ module ShopifyCli
125
97
  "https://#{domain}"
126
98
  end
127
99
 
128
- def scopes
129
- %w[openid https://api.shopify.com/auth/partners.app.cli.access].tap do |result|
130
- result << "employee" if ShopifyCli::Shopifolk.acting_as_shopify_organization?
100
+ def auth_failure_info(ctx, error)
101
+ if error.response
102
+ headers = %w(www-authenticate x-request-id)
103
+ request_info = headers.map { |h| "#{h}: #{error.response[h]}" if error.response.key?(h) }.join("\n")
104
+ ctx.debug("Full headers: #{error.response.each_header.to_h}")
105
+ request_info
131
106
  end
107
+ rescue => e
108
+ ctx.debug("Couldn't fetch auth failure information from #{error}: #{e}")
132
109
  end
133
110
  end
134
111