shopify-cli 1.11.0 → 2.0.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 +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/CONTRIBUTING.md +7 -7
- data/.github/DESIGN.md +3 -3
- data/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- data/.github/workflows/build.yml +1 -1
- data/.gitignore +3 -0
- data/.rubocop.yml +3 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +48 -20
- data/Gemfile +4 -0
- data/Gemfile.lock +32 -0
- data/LICENSE +4 -1
- data/README.md +92 -26
- data/RELEASING.md +29 -7
- data/Rakefile +2 -2
- data/SECURITY.md +1 -1
- data/bin/load_shopify.rb +1 -1
- data/bin/shopify +3 -3
- data/dev.yml +1 -1
- data/docs/app/node/index.md +1 -1
- data/docs/app/rails/index.md +1 -1
- data/docs/core/index.md +1 -1
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/install/index.md +1 -1
- data/docs/getting-started/migrate/index.md +1 -1
- data/docs/getting-started/uninstall/index.md +1 -1
- data/docs/getting-started/upgrade/index.md +1 -1
- data/docs/help/start-app/index.md +1 -1
- data/docs/index.md +1 -1
- data/ext/shopify-cli/extconf.rb +17 -5
- data/install.sh +1 -1
- data/lib/docgen/index_template.md.erb +2 -2
- data/lib/graphql/all_orgs_with_extensions.graphql +37 -0
- data/lib/graphql/find_organization.graphql +2 -1
- data/lib/project_types/extension/cli.rb +18 -15
- data/lib/project_types/extension/commands/build.rb +4 -5
- data/lib/project_types/extension/commands/connect.rb +35 -0
- data/lib/project_types/extension/commands/create.rb +12 -16
- data/lib/project_types/extension/commands/extension_command.rb +2 -2
- data/lib/project_types/extension/commands/info.rb +86 -0
- data/lib/project_types/extension/commands/push.rb +8 -7
- data/lib/project_types/extension/commands/register.rb +4 -5
- data/lib/project_types/extension/commands/serve.rb +5 -8
- data/lib/project_types/extension/commands/tunnel.rb +3 -1
- data/lib/project_types/extension/errors.rb +9 -0
- data/lib/project_types/extension/extension_project.rb +5 -0
- data/lib/project_types/extension/features/argo.rb +6 -6
- data/lib/project_types/extension/features/argo_runtime.rb +22 -38
- data/lib/project_types/extension/features/argo_serve.rb +25 -20
- data/lib/project_types/extension/forms/connect.rb +42 -0
- data/lib/project_types/extension/forms/questions/ask_name.rb +14 -6
- data/lib/project_types/extension/forms/questions/ask_registration.rb +51 -0
- data/lib/project_types/extension/messages/messages.rb +75 -11
- data/lib/project_types/extension/models/specification.rb +1 -0
- data/lib/project_types/extension/models/specification_handlers/{checkout_argo_extension.rb → checkout_ui_extension.rb} +3 -1
- data/lib/project_types/extension/models/specification_handlers/default.rb +21 -6
- data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +86 -0
- data/lib/project_types/extension/models/specifications.rb +1 -0
- data/lib/project_types/extension/tasks/configure_features.rb +6 -7
- data/lib/project_types/extension/tasks/configure_options.rb +20 -0
- data/lib/project_types/extension/tasks/get_extensions.rb +32 -0
- data/lib/project_types/node/cli.rb +9 -21
- data/lib/project_types/node/commands/connect.rb +8 -2
- data/lib/project_types/node/commands/create.rb +9 -5
- data/lib/project_types/node/commands/deploy.rb +15 -5
- data/lib/project_types/node/commands/deploy/heroku.rb +29 -29
- data/lib/project_types/node/commands/generate.rb +4 -2
- data/lib/project_types/node/commands/open.rb +4 -2
- data/lib/project_types/node/commands/serve.rb +3 -2
- data/lib/project_types/node/commands/tunnel.rb +4 -2
- data/lib/project_types/node/messages/messages.rb +46 -89
- data/lib/project_types/rails/cli.rb +9 -21
- data/lib/project_types/rails/commands/connect.rb +8 -2
- data/lib/project_types/rails/commands/create.rb +10 -6
- data/lib/project_types/rails/commands/deploy.rb +15 -5
- data/lib/project_types/rails/commands/deploy/heroku.rb +84 -82
- data/lib/project_types/rails/commands/generate.rb +15 -5
- data/lib/project_types/rails/commands/generate/webhook.rb +28 -26
- data/lib/project_types/rails/commands/open.rb +4 -2
- data/lib/project_types/rails/commands/serve.rb +3 -2
- data/lib/project_types/rails/commands/tunnel.rb +4 -2
- data/lib/project_types/rails/messages/messages.rb +54 -101
- data/lib/project_types/script/cli.rb +18 -20
- data/lib/project_types/script/commands/create.rb +3 -1
- data/lib/project_types/script/commands/push.rb +12 -5
- data/lib/project_types/script/config/extension_points.yml +0 -3
- data/lib/project_types/script/graphql/app_script_update_or_create.graphql +9 -3
- data/lib/project_types/script/layers/application/create_script.rb +6 -5
- data/lib/project_types/script/layers/application/push_script.rb +2 -1
- data/lib/project_types/script/layers/domain/errors.rb +6 -11
- data/lib/project_types/script/layers/domain/push_package.rb +4 -8
- data/lib/project_types/script/layers/domain/script_json.rb +32 -0
- data/lib/project_types/script/layers/domain/script_project.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/errors.rb +14 -18
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +105 -0
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +103 -0
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +26 -0
- data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +73 -0
- data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +60 -0
- data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +21 -0
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +2 -4
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +45 -34
- data/lib/project_types/script/layers/infrastructure/script_service.rb +20 -14
- data/lib/project_types/script/messages/messages.rb +66 -55
- data/lib/project_types/script/tasks/ensure_env.rb +22 -1
- data/lib/project_types/script/ui/error_handler.rb +32 -32
- data/lib/project_types/theme/cli.rb +15 -27
- data/lib/project_types/theme/commands/check.rb +33 -0
- data/lib/project_types/theme/commands/delete.rb +64 -0
- data/lib/project_types/theme/commands/language_server.rb +16 -0
- data/lib/project_types/theme/commands/package.rb +55 -0
- data/lib/project_types/theme/commands/publish.rb +43 -0
- data/lib/project_types/theme/commands/pull.rb +51 -0
- data/lib/project_types/theme/commands/push.rb +58 -32
- data/lib/project_types/theme/commands/serve.rb +7 -17
- data/lib/project_types/theme/forms/confirm_store.rb +15 -0
- data/lib/project_types/theme/forms/select.rb +59 -0
- data/lib/project_types/theme/messages/messages.rb +110 -106
- data/lib/project_types/theme/ui/sync_progress_bar.rb +20 -0
- data/lib/shopify-cli/admin_api.rb +53 -35
- data/lib/shopify-cli/admin_api/populate_resource_command.rb +6 -14
- data/lib/shopify-cli/admin_api/schema.rb +1 -10
- data/lib/shopify-cli/api.rb +29 -14
- data/lib/shopify-cli/command.rb +15 -3
- data/lib/shopify-cli/commands.rb +7 -2
- data/lib/shopify-cli/commands/help.rb +2 -29
- data/lib/shopify-cli/commands/login.rb +95 -0
- data/lib/shopify-cli/commands/logout.rb +24 -8
- data/lib/shopify-cli/commands/populate.rb +23 -0
- data/lib/{project_types/node → shopify-cli}/commands/populate/customer.rb +2 -8
- data/lib/{project_types/node → shopify-cli}/commands/populate/draft_order.rb +2 -2
- data/lib/{project_types/node → shopify-cli}/commands/populate/product.rb +2 -8
- data/lib/shopify-cli/commands/store.rb +15 -0
- data/lib/shopify-cli/commands/switch.rb +39 -0
- data/lib/shopify-cli/commands/system.rb +12 -0
- data/lib/shopify-cli/commands/whoami.rb +28 -0
- data/lib/shopify-cli/connect.rb +32 -0
- data/lib/shopify-cli/context.rb +65 -4
- data/lib/shopify-cli/core/entry_point.rb +3 -22
- data/lib/shopify-cli/db.rb +4 -4
- data/lib/shopify-cli/http_request.rb +10 -0
- data/lib/shopify-cli/identity_auth.rb +282 -0
- data/lib/shopify-cli/{oauth → identity_auth}/servlet.rb +11 -12
- data/lib/shopify-cli/messages/messages.rb +133 -39
- data/lib/shopify-cli/partners_api.rb +21 -41
- data/lib/shopify-cli/partners_api/organizations.rb +8 -0
- data/lib/shopify-cli/project_commands.rb +16 -0
- data/lib/shopify-cli/project_type.rb +0 -31
- data/lib/shopify-cli/resources/env_file.rb +1 -1
- data/lib/shopify-cli/shopifolk.rb +8 -11
- data/lib/shopify-cli/sub_command.rb +1 -0
- data/lib/shopify-cli/tasks.rb +3 -0
- data/lib/shopify-cli/tasks/confirm_store.rb +18 -0
- data/lib/shopify-cli/tasks/create_api_client.rb +2 -2
- data/lib/shopify-cli/tasks/ensure_authenticated.rb +13 -0
- data/lib/shopify-cli/tasks/ensure_loopback_url.rb +1 -1
- data/lib/shopify-cli/tasks/ensure_project_type.rb +12 -0
- data/lib/shopify-cli/tasks/select_org_and_shop.rb +0 -3
- data/lib/shopify-cli/theme/dev_server.rb +98 -0
- data/lib/shopify-cli/theme/dev_server/certificate_manager.rb +79 -0
- data/lib/shopify-cli/theme/dev_server/header_hash.rb +94 -0
- data/lib/shopify-cli/theme/dev_server/hot-reload.js +93 -0
- data/lib/shopify-cli/theme/dev_server/hot_reload.rb +76 -0
- data/lib/shopify-cli/theme/dev_server/local_assets.rb +87 -0
- data/lib/shopify-cli/theme/dev_server/proxy.rb +205 -0
- data/lib/shopify-cli/theme/dev_server/sse.rb +75 -0
- data/lib/shopify-cli/theme/dev_server/watcher.rb +59 -0
- data/lib/shopify-cli/theme/dev_server/web_server.rb +140 -0
- data/lib/shopify-cli/theme/development_theme.rb +69 -0
- data/lib/shopify-cli/theme/file.rb +112 -0
- data/lib/shopify-cli/theme/ignore_filter.rb +109 -0
- data/lib/shopify-cli/theme/mime_type.rb +34 -0
- data/lib/shopify-cli/theme/syncer.rb +328 -0
- data/lib/shopify-cli/theme/theme.rb +204 -0
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +18 -11
- data/shopify-cli.gemspec +12 -5
- data/shopify.fish +1 -1
- data/shopify.sh +1 -1
- metadata +95 -41
- data/.github/workflows/release.yml +0 -61
- data/lib/project_types/extension/features/argo_serve_options.rb +0 -40
- data/lib/project_types/node/commands/populate.rb +0 -23
- data/lib/project_types/rails/commands/populate.rb +0 -23
- data/lib/project_types/rails/commands/populate/customer.rb +0 -31
- data/lib/project_types/rails/commands/populate/draft_order.rb +0 -28
- data/lib/project_types/rails/commands/populate/product.rb +0 -30
- data/lib/project_types/script/layers/domain/config_ui.rb +0 -16
- data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +0 -95
- data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +0 -101
- data/lib/project_types/script/layers/infrastructure/project_creator.rb +0 -24
- data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +0 -71
- data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +0 -58
- data/lib/project_types/script/layers/infrastructure/task_runner.rb +0 -19
- data/lib/project_types/theme/commands/connect.rb +0 -54
- data/lib/project_types/theme/commands/create.rb +0 -48
- data/lib/project_types/theme/commands/deploy.rb +0 -38
- data/lib/project_types/theme/commands/generate.rb +0 -20
- data/lib/project_types/theme/commands/generate/env.rb +0 -79
- data/lib/project_types/theme/forms/connect.rb +0 -34
- data/lib/project_types/theme/forms/create.rb +0 -22
- data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +0 -78
- data/lib/project_types/theme/themekit.rb +0 -113
- data/lib/shopify-cli/commands/connect.rb +0 -64
- data/lib/shopify-cli/commands/create.rb +0 -50
- data/lib/shopify-cli/oauth.rb +0 -198
|
@@ -8,11 +8,21 @@ module ShopifyCli
|
|
|
8
8
|
request(uri, body, headers, req)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def put(uri, body, headers)
|
|
12
|
+
req = ::Net::HTTP::Put.new(uri.request_uri)
|
|
13
|
+
request(uri, body, headers, req)
|
|
14
|
+
end
|
|
15
|
+
|
|
11
16
|
def get(uri, body, headers)
|
|
12
17
|
req = ::Net::HTTP::Get.new(uri.request_uri)
|
|
13
18
|
request(uri, body, headers, req)
|
|
14
19
|
end
|
|
15
20
|
|
|
21
|
+
def delete(uri, body, headers)
|
|
22
|
+
req = ::Net::HTTP::Delete.new(uri.request_uri)
|
|
23
|
+
request(uri, body, headers, req)
|
|
24
|
+
end
|
|
25
|
+
|
|
16
26
|
def request(uri, body, headers, req)
|
|
17
27
|
http = ::Net::HTTP.new(uri.host, uri.port)
|
|
18
28
|
http.use_ssl = true
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
require "base64"
|
|
2
|
+
require "digest"
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "securerandom"
|
|
6
|
+
require "openssl"
|
|
7
|
+
require "shopify_cli"
|
|
8
|
+
require "uri"
|
|
9
|
+
require "webrick"
|
|
10
|
+
|
|
11
|
+
module ShopifyCli
|
|
12
|
+
class IdentityAuth
|
|
13
|
+
include SmartProperties
|
|
14
|
+
|
|
15
|
+
autoload :Servlet, "shopify-cli/identity_auth/servlet"
|
|
16
|
+
|
|
17
|
+
class Error < StandardError; end
|
|
18
|
+
class Timeout < StandardError; end
|
|
19
|
+
LocalRequest = Struct.new(:method, :path, :query, :protocol)
|
|
20
|
+
LOCAL_DEBUG = "SHOPIFY_APP_CLI_LOCAL_PARTNERS"
|
|
21
|
+
|
|
22
|
+
DEFAULT_PORT = 3456
|
|
23
|
+
REDIRECT_HOST = "http://127.0.0.1:#{DEFAULT_PORT}"
|
|
24
|
+
|
|
25
|
+
APPLICATION_SCOPES = {
|
|
26
|
+
"shopify" => %w[https://api.shopify.com/auth/shop.admin.graphql https://api.shopify.com/auth/shop.admin.themes https://api.shopify.com/auth/partners.collaborator-relationships.readonly],
|
|
27
|
+
"storefront_renderer_production" => %w[https://api.shopify.com/auth/shop.storefront-renderer.devtools],
|
|
28
|
+
"partners" => %w[https://api.shopify.com/auth/partners.app.cli.access],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
APPLICATION_CLIENT_IDS = {
|
|
32
|
+
"shopify" => "7ee65a63608843c577db8b23c4d7316ea0a01bd2f7594f8a9c06ea668c1b775c",
|
|
33
|
+
"storefront_renderer_production" => "ee139b3d-5861-4d45-b387-1bc3ada7811c",
|
|
34
|
+
"partners" => "271e16d403dfa18082ffb3d197bd2b5f4479c3fc32736d69296829cbb28d41a6",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
DEV_APPLICATION_CLIENT_IDS = {
|
|
38
|
+
"shopify" => "e92482cebb9bfb9fb5a0199cc770fde3de6c8d16b798ee73e36c9d815e070e52",
|
|
39
|
+
"storefront_renderer_production" => "46f603de-894f-488d-9471-5b721280ff49",
|
|
40
|
+
"partners" => "df89d73339ac3c6c5f0a98d9ca93260763e384d51d6038da129889c308973978",
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
EXCHANGE_TOKENS = APPLICATION_SCOPES.keys.map do |key|
|
|
44
|
+
"#{key}_exchange_token".to_sym
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
IDENTITY_ACCESS_TOKENS = %i[
|
|
48
|
+
identity_access_token
|
|
49
|
+
identity_refresh_token
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
property! :ctx
|
|
53
|
+
property :store, default: -> { ShopifyCli::DB.new }
|
|
54
|
+
property :state_token, accepts: String, default: SecureRandom.hex(30)
|
|
55
|
+
property :code_verifier, accepts: String, default: SecureRandom.hex(30)
|
|
56
|
+
|
|
57
|
+
attr_accessor :response_query
|
|
58
|
+
|
|
59
|
+
def authenticate
|
|
60
|
+
return if refresh_exchange_tokens || refresh_access_tokens
|
|
61
|
+
|
|
62
|
+
initiate_authentication
|
|
63
|
+
|
|
64
|
+
begin
|
|
65
|
+
request_access_token(code: receive_access_code)
|
|
66
|
+
rescue IdentityAuth::Timeout => e
|
|
67
|
+
ctx.abort(e.message)
|
|
68
|
+
end
|
|
69
|
+
request_exchange_tokens
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def reauthenticate
|
|
73
|
+
return if refresh_exchange_tokens || refresh_access_tokens
|
|
74
|
+
ctx.abort(ctx.message("core.identity_auth.error.reauthenticate", ShopifyCli::TOOL_NAME))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def code_challenge
|
|
78
|
+
@code_challenge ||= Base64.urlsafe_encode64(
|
|
79
|
+
OpenSSL::Digest::SHA256.digest(code_verifier),
|
|
80
|
+
padding: false,
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def server
|
|
85
|
+
@server ||= begin
|
|
86
|
+
server = WEBrick::HTTPServer.new(
|
|
87
|
+
Port: DEFAULT_PORT,
|
|
88
|
+
Logger: WEBrick::Log.new(File.open(File::NULL, "w")),
|
|
89
|
+
AccessLog: [],
|
|
90
|
+
)
|
|
91
|
+
server.mount("/", Servlet, self, state_token)
|
|
92
|
+
server
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.delete_tokens_and_keys
|
|
97
|
+
ShopifyCli::DB.del(*IDENTITY_ACCESS_TOKENS)
|
|
98
|
+
ShopifyCli::DB.del(*EXCHANGE_TOKENS)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def initiate_authentication
|
|
104
|
+
@server_thread = Thread.new { server.start }
|
|
105
|
+
params = {
|
|
106
|
+
client_id: client_id,
|
|
107
|
+
scope: scopes(APPLICATION_SCOPES.values.flatten),
|
|
108
|
+
redirect_uri: REDIRECT_HOST,
|
|
109
|
+
state: state_token,
|
|
110
|
+
response_type: :code,
|
|
111
|
+
}
|
|
112
|
+
params.merge!(challange_params)
|
|
113
|
+
uri = URI.parse("#{auth_url}/authorize")
|
|
114
|
+
uri.query = URI.encode_www_form(params)
|
|
115
|
+
open_browser_authentication(uri)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def open_browser_authentication(uri)
|
|
119
|
+
ctx.open_browser_url!(uri)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def receive_access_code
|
|
123
|
+
@access_code ||= begin
|
|
124
|
+
@server_thread.join(240)
|
|
125
|
+
raise Timeout, ctx.message("core.identity_auth.error.timeout") if response_query.nil?
|
|
126
|
+
raise Error, response_query["error_description"] unless response_query["error"].nil?
|
|
127
|
+
response_query["code"]
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def request_access_token(code:)
|
|
132
|
+
resp = post_token_request(
|
|
133
|
+
grant_type: :authorization_code,
|
|
134
|
+
code: code,
|
|
135
|
+
redirect_uri: REDIRECT_HOST,
|
|
136
|
+
client_id: client_id,
|
|
137
|
+
code_verifier: code_verifier,
|
|
138
|
+
)
|
|
139
|
+
store.set(
|
|
140
|
+
identity_access_token: resp["access_token"],
|
|
141
|
+
identity_refresh_token: resp["refresh_token"],
|
|
142
|
+
)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def refresh_access_tokens
|
|
146
|
+
return false unless IDENTITY_ACCESS_TOKENS.all? { |key| store.exists?(key) }
|
|
147
|
+
|
|
148
|
+
resp = post_token_request(
|
|
149
|
+
grant_type: :refresh_token,
|
|
150
|
+
access_token: store.get(:identity_access_token),
|
|
151
|
+
refresh_token: store.get(:identity_refresh_token),
|
|
152
|
+
client_id: client_id,
|
|
153
|
+
)
|
|
154
|
+
store.set(
|
|
155
|
+
identity_access_token: resp["access_token"],
|
|
156
|
+
identity_refresh_token: resp["refresh_token"],
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Need to refresh the exchange token on successful access token refresh
|
|
160
|
+
request_exchange_tokens
|
|
161
|
+
|
|
162
|
+
true
|
|
163
|
+
rescue
|
|
164
|
+
store.del(*IDENTITY_ACCESS_TOKENS)
|
|
165
|
+
false
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def refresh_exchange_tokens
|
|
169
|
+
return false unless EXCHANGE_TOKENS.all? { |key| store.exists?(key) }
|
|
170
|
+
|
|
171
|
+
request_exchange_tokens
|
|
172
|
+
|
|
173
|
+
true
|
|
174
|
+
rescue
|
|
175
|
+
store.del(*EXCHANGE_TOKENS)
|
|
176
|
+
false
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def request_exchange_tokens
|
|
180
|
+
APPLICATION_SCOPES.each do |key, scopes|
|
|
181
|
+
request_exchange_token(key, client_id_for_application(key), scopes)
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def request_exchange_token(name, audience, additional_scopes)
|
|
186
|
+
return if name == "shopify" && !store.exists?(:shop)
|
|
187
|
+
|
|
188
|
+
params = {
|
|
189
|
+
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
190
|
+
requested_token_type: "urn:ietf:params:oauth:token-type:access_token",
|
|
191
|
+
subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
|
|
192
|
+
client_id: client_id,
|
|
193
|
+
audience: audience,
|
|
194
|
+
scope: scopes(additional_scopes),
|
|
195
|
+
subject_token: store.get(:identity_access_token),
|
|
196
|
+
}.tap do |result|
|
|
197
|
+
if name == "shopify"
|
|
198
|
+
result[:destination] = "https://#{store.get(:shop)}/admin"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
# ctx.debug(params)
|
|
202
|
+
resp = post_token_request(params)
|
|
203
|
+
store.set("#{name}_exchange_token".to_sym => resp["access_token"])
|
|
204
|
+
ctx.debug("#{name}_exchange_token: " + resp["access_token"])
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def post_token_request(params)
|
|
208
|
+
post_request("/token", params)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def post_request(endpoint, params)
|
|
212
|
+
uri = URI.parse("#{auth_url}#{endpoint}")
|
|
213
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
|
214
|
+
https.use_ssl = true
|
|
215
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
216
|
+
request["User-Agent"] = "Shopify CLI #{::ShopifyCli::VERSION}"
|
|
217
|
+
request.body = URI.encode_www_form(params)
|
|
218
|
+
res = https.request(request)
|
|
219
|
+
unless res.is_a?(Net::HTTPSuccess)
|
|
220
|
+
error_msg = JSON.parse(res.body)["error_description"]
|
|
221
|
+
shop = store.get(:shop)
|
|
222
|
+
if error_msg.include?("destination")
|
|
223
|
+
store.del(:shop)
|
|
224
|
+
ctx.abort(ctx.message("core.identity_auth.error.invalid_destination", shop))
|
|
225
|
+
end
|
|
226
|
+
raise Error, error_msg
|
|
227
|
+
end
|
|
228
|
+
JSON.parse(res.body)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def challange_params
|
|
232
|
+
{
|
|
233
|
+
code_challenge: code_challenge,
|
|
234
|
+
code_challenge_method: "S256",
|
|
235
|
+
}
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def auth_url
|
|
239
|
+
return "https://accounts.shopify.com/oauth" if ENV[LOCAL_DEBUG].nil?
|
|
240
|
+
"https://identity.myshopify.io/oauth"
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def client_id_for_application(application_name)
|
|
244
|
+
client_ids = if ENV[LOCAL_DEBUG]
|
|
245
|
+
DEV_APPLICATION_CLIENT_IDS
|
|
246
|
+
else
|
|
247
|
+
APPLICATION_CLIENT_IDS
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
client_ids[application_name]
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def scopes(additional_scopes = [])
|
|
254
|
+
(["openid"] + additional_scopes).tap do |result|
|
|
255
|
+
result << "employee" if ShopifyCli::Shopifolk.acting_as_shopify_organization?
|
|
256
|
+
end.join(" ")
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def client_id
|
|
260
|
+
return "fbdb2649-e327-4907-8f67-908d24cfd7e3" if ENV[LOCAL_DEBUG].nil?
|
|
261
|
+
|
|
262
|
+
ctx.abort(ctx.message("core.identity_auth.error.local_identity_not_running")) unless local_identity_running?
|
|
263
|
+
|
|
264
|
+
# Fetch the client ID from the local Identity Dynamic Registration endpoint
|
|
265
|
+
response = post_request("/client", {
|
|
266
|
+
name: "shopify-cli-development",
|
|
267
|
+
public_type: "native",
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
response["client_id"]
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def local_identity_running?
|
|
274
|
+
Net::HTTP.start("identity.myshopify.io", 443, use_ssl: true, open_timeout: 1, read_timeout: 10) do |http|
|
|
275
|
+
req = Net::HTTP::Get.new(URI.join("https://identity.myshopify.io", "/services/ping"))
|
|
276
|
+
http.request(req).is_a?(Net::HTTPSuccess)
|
|
277
|
+
end
|
|
278
|
+
rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::EHOSTDOWN, Errno::EADDRNOTAVAIL, Errno::ECONNREFUSED
|
|
279
|
+
false
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module ShopifyCli
|
|
2
|
-
class
|
|
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,
|
|
19
|
+
def initialize(server, identity_auth, token)
|
|
22
20
|
super
|
|
23
21
|
@server = server
|
|
24
|
-
@
|
|
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.
|
|
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.
|
|
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.
|
|
38
|
+
respond_with(res, 200, Context.message("core.identity_auth.servlet.success_response"))
|
|
41
39
|
end
|
|
42
|
-
@
|
|
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
|
-
|
|
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
|
|
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
|
|
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: "
|
|
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
|
-
|
|
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: {
|
|
@@ -184,6 +190,11 @@ module ShopifyCli
|
|
|
184
190
|
|
|
185
191
|
api: {
|
|
186
192
|
error: {
|
|
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
|
|
187
198
|
internal_server_error: "{{red:{{x}} An unexpected error occurred on Shopify.}}",
|
|
188
199
|
internal_server_error_debug: "\n{{red:Response details:}}\n%s\n\n",
|
|
189
200
|
invalid_url: "Invalid URL: %s",
|
|
@@ -191,22 +202,78 @@ module ShopifyCli
|
|
|
191
202
|
},
|
|
192
203
|
|
|
193
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
|
+
|
|
194
255
|
options: {
|
|
195
256
|
header: "{{bold:{{cyan:%s}} options:}}",
|
|
196
257
|
count_help: "Number of resources to generate",
|
|
197
258
|
},
|
|
259
|
+
|
|
198
260
|
populating: "Populating %d %ss...",
|
|
261
|
+
|
|
199
262
|
completion_message: <<~COMPLETION_MESSAGE,
|
|
200
263
|
Successfully added %d %s to {{green:%s}}
|
|
201
264
|
{{*}} View all %ss at {{underline:%s%ss}}
|
|
202
265
|
COMPLETION_MESSAGE
|
|
266
|
+
|
|
267
|
+
product: {
|
|
268
|
+
added: "%s added to {{green:%s}} at {{underline:%sproducts/%d}}",
|
|
269
|
+
},
|
|
203
270
|
},
|
|
204
271
|
|
|
205
272
|
project: {
|
|
206
273
|
error: {
|
|
207
274
|
not_in_project: <<~MESSAGE,
|
|
208
275
|
{{x}} You are not in a Shopify app project
|
|
209
|
-
{{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}}
|
|
210
277
|
MESSAGE
|
|
211
278
|
},
|
|
212
279
|
},
|
|
@@ -238,7 +305,8 @@ module ShopifyCli
|
|
|
238
305
|
unknown_option: "{{x}} {{red:unknown option '%s'}}",
|
|
239
306
|
},
|
|
240
307
|
|
|
241
|
-
header: "{{bold:Shopify
|
|
308
|
+
header: "{{bold:Shopify CLI}}",
|
|
309
|
+
shop_header: "{{bold:Current Shop}}",
|
|
242
310
|
const: "%17s = %s",
|
|
243
311
|
ruby_header: <<~RUBY_MESSAGE,
|
|
244
312
|
{{bold:Ruby (via RbConfig)}}
|
|
@@ -265,7 +333,20 @@ module ShopifyCli
|
|
|
265
333
|
identity_is_shopifolk: "{{v}} Checked user settings: you’re Shopify staff!",
|
|
266
334
|
},
|
|
267
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
|
+
|
|
268
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
|
+
},
|
|
269
350
|
ensure_env: {
|
|
270
351
|
organization_select: "To which partner organization does this project belong?",
|
|
271
352
|
no_development_stores: <<~MESSAGE,
|
|
@@ -292,6 +373,9 @@ module ShopifyCli
|
|
|
292
373
|
MESSAGE
|
|
293
374
|
transfer_disabled: "{{v}} Transfer has been disabled on %s.",
|
|
294
375
|
},
|
|
376
|
+
ensure_project_type: {
|
|
377
|
+
wrong_project_type: "This command can only be run within %s projects.",
|
|
378
|
+
},
|
|
295
379
|
update_dashboard_urls: {
|
|
296
380
|
updated: "{{v}} Whitelist URLS updated in Partners Dashboard}}",
|
|
297
381
|
update_error:
|
|
@@ -309,10 +393,11 @@ module ShopifyCli
|
|
|
309
393
|
organization_not_found: "Cannot find a partner organization with that ID",
|
|
310
394
|
shopifolk_notice: <<~MESSAGE,
|
|
311
395
|
{{i}} As a {{green:Shopify}} employee, the authentication should take you to the Shopify Okta login,
|
|
312
|
-
NOT the
|
|
396
|
+
NOT the partner account login. Please run {{command:%s logout}} and try again.
|
|
313
397
|
MESSAGE
|
|
314
398
|
},
|
|
315
|
-
first_party: "Are you working on a
|
|
399
|
+
first_party: "Are you working on a {{green:Shopify project}} on behalf of the"\
|
|
400
|
+
" {{green:Shopify partners org}}?",
|
|
316
401
|
identified_as_shopify: "We've identified you as a {{green:Shopify}} employee.",
|
|
317
402
|
organization: "Partner organization {{green:%s (%s)}}",
|
|
318
403
|
organization_select: "Select partner organization",
|
|
@@ -333,7 +418,7 @@ module ShopifyCli
|
|
|
333
418
|
signup_suggestion: <<~MESSAGE,
|
|
334
419
|
{{*}} To avoid tunnels that timeout, it is recommended to signup for a free ngrok
|
|
335
420
|
account at {{underline:https://ngrok.com/signup}}. After you signup, install your
|
|
336
|
-
personalized authorization token using {{command:%s tunnel auth <token>}}.
|
|
421
|
+
personalized authorization token using {{command:%s [ node | rails ] tunnel auth <token>}}.
|
|
337
422
|
MESSAGE
|
|
338
423
|
start: "{{v}} ngrok tunnel running at {{underline:%s}}",
|
|
339
424
|
start_with_account: "{{v}} ngrok tunnel running at {{underline:%s}}, with account %s",
|
|
@@ -357,21 +442,30 @@ module ShopifyCli
|
|
|
357
442
|
|
|
358
443
|
DEVELOPMENT
|
|
359
444
|
|
|
360
|
-
|
|
361
|
-
{{
|
|
445
|
+
new_version: <<~MESSAGE,
|
|
446
|
+
{{*}} {{yellow:A new version of Shopify CLI is available! You have version %s and the latest version is %s.
|
|
362
447
|
|
|
363
|
-
|
|
364
|
-
{{underline:https://shopify.dev/tools/cli/troubleshooting#
|
|
448
|
+
To upgrade, follow the instructions for the package manager you’re using:
|
|
449
|
+
{{underline:https://shopify.dev/tools/cli/troubleshooting#upgrade-shopify-cli}}}}
|
|
365
450
|
|
|
366
451
|
MESSAGE
|
|
452
|
+
},
|
|
367
453
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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.
|
|
373
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)
|
|
374
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}}",
|
|
375
469
|
},
|
|
376
470
|
},
|
|
377
471
|
}.freeze
|