asca 0.1.0 → 1.0.2
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/.gitignore +1 -0
- data/Gemfile.lock +23 -2
- data/README.md +32 -8
- data/app-store-connect-openapi-spec.json +32545 -0
- data/asca.gemspec +2 -1
- data/exe/asca +62 -12
- data/lib/asca.rb +10 -3
- data/lib/asca/consts.rb +3 -0
- data/lib/asca/rest/provisioning/bundleids.rb +22 -0
- data/lib/asca/rest/provisioning/certificates.rb +32 -0
- data/lib/asca/rest/provisioning/devices.rb +40 -0
- data/lib/asca/rest/provisioning/profiles.rb +167 -0
- data/lib/asca/tools/configuration.rb +57 -0
- data/lib/asca/tools/log.rb +55 -0
- data/lib/asca/tools/token.rb +102 -0
- data/lib/asca/tools/tools.rb +22 -0
- data/lib/asca/version.rb +1 -1
- metadata +12 -6
- data/lib/asca/configuration.rb +0 -55
- data/lib/asca/profiles.rb +0 -36
- data/lib/asca/token.rb +0 -92
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'jwt'
|
3
|
+
|
4
|
+
module Asca
|
5
|
+
module Tools
|
6
|
+
class Token
|
7
|
+
EXPIRE_DURATION = 20 * 60
|
8
|
+
class << self
|
9
|
+
# Generate new jwt token.
|
10
|
+
def new_token
|
11
|
+
# get token from cache
|
12
|
+
token = get_token_from_cache
|
13
|
+
if token
|
14
|
+
return token
|
15
|
+
end
|
16
|
+
|
17
|
+
# get kid
|
18
|
+
kid = Asca::Tools::Configuration.get_config('kid')
|
19
|
+
if !kid
|
20
|
+
Asca::Tools::Log.info "Before generating a jwt token, please enter your kid:"
|
21
|
+
kid = gets.chomp
|
22
|
+
Asca::Tools::Configuration.update_config('kid', kid)
|
23
|
+
end
|
24
|
+
if !kid
|
25
|
+
Asca::Tools::Log.error "Error: no kid!"
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
# get issuer id
|
30
|
+
iss = Asca::Tools::Configuration.get_config('iss')
|
31
|
+
if !iss
|
32
|
+
Asca::Tools::Log.info "Before generating a jwt token, please enter your issuer id:"
|
33
|
+
iss = gets.chomp
|
34
|
+
Asca::Tools::Configuration.update_config('iss', iss)
|
35
|
+
end
|
36
|
+
if !iss
|
37
|
+
Asca::Tools::Log.error "Error: no issuer id!"
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
# get private key
|
42
|
+
private_key = Asca::Tools::Configuration.get_config('private_key')
|
43
|
+
if !private_key
|
44
|
+
Asca::Tools::Log.info "Before generating a jwt token, please enter your private key path:"
|
45
|
+
private_key_path = gets.chomp
|
46
|
+
private_key = File.read private_key_path
|
47
|
+
Asca::Tools::Configuration.update_config('private_key', private_key)
|
48
|
+
end
|
49
|
+
if !private_key
|
50
|
+
Asca::Tools::Log.error "Error: no private key!"
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
# generate jwt header
|
55
|
+
jwt_header = {
|
56
|
+
"alg": "ES256",
|
57
|
+
"kid": kid,
|
58
|
+
"typ": "JWT"
|
59
|
+
}
|
60
|
+
|
61
|
+
# generate jwt payload
|
62
|
+
exp = Time.now.to_i + EXPIRE_DURATION
|
63
|
+
jwt_payload = {
|
64
|
+
"iss": iss,
|
65
|
+
"exp": exp,
|
66
|
+
"aud": "appstoreconnect-v1"
|
67
|
+
}
|
68
|
+
|
69
|
+
begin
|
70
|
+
es_key = OpenSSL::PKey::EC.new private_key
|
71
|
+
rescue => exception
|
72
|
+
Asca::Tools::Log.info "Invalid private key, please enter your correct private key path:"
|
73
|
+
private_key_path = gets.chomp
|
74
|
+
private_key = File.read private_key_path
|
75
|
+
Asca::Tools::Configuration.update_config('private_key', private_key)
|
76
|
+
es_key = OpenSSL::PKey::EC.new private_key
|
77
|
+
end
|
78
|
+
|
79
|
+
token = JWT.encode jwt_payload, es_key, 'ES256', jwt_header
|
80
|
+
Asca::Tools::Configuration.update_config('cache_token_time', exp)
|
81
|
+
Asca::Tools::Configuration.update_config('cache_token', token)
|
82
|
+
Asca::Tools::Log.info "==== New token generated ===="
|
83
|
+
Asca::Tools::Log.info token
|
84
|
+
Asca::Tools::Log.info "============================="
|
85
|
+
return token
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_token_from_cache
|
89
|
+
token_valid_max_time = Asca::Tools::Configuration.get_config('cache_token_time')
|
90
|
+
if !token_valid_max_time
|
91
|
+
return nil
|
92
|
+
end
|
93
|
+
current = Time.now.to_i
|
94
|
+
if token_valid_max_time > current
|
95
|
+
return Asca::Tools::Configuration.get_config('cache_token')
|
96
|
+
end
|
97
|
+
return nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'http'
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module Asca
|
5
|
+
module Tools
|
6
|
+
# register a new device and update corresponding profiles
|
7
|
+
def self.register_device(options = {})
|
8
|
+
device_info = options[:device_info]
|
9
|
+
profile_names = options[:profile_names]
|
10
|
+
if !device_info || !profile_names
|
11
|
+
Asca::Tools::Log.error('Wrong parameters for register device')
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
Asca::REST::Provisioning::Devices.register_new_device :udid => device_info[:udid], :name => device_info[:name]
|
16
|
+
|
17
|
+
profile_names.each { |profile_name|
|
18
|
+
Asca::REST::Provisioning::Profiles.update_profile :name => profile_name
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/asca/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asca
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- xueminghao
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: http
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -111,15 +111,21 @@ files:
|
|
111
111
|
- LICENSE.txt
|
112
112
|
- README.md
|
113
113
|
- Rakefile
|
114
|
+
- app-store-connect-openapi-spec.json
|
114
115
|
- asca.gemspec
|
115
116
|
- bin/console
|
116
117
|
- bin/setup
|
117
118
|
- exe/asca
|
118
119
|
- lib/asca.rb
|
119
|
-
- lib/asca/configuration.rb
|
120
120
|
- lib/asca/consts.rb
|
121
|
-
- lib/asca/
|
122
|
-
- lib/asca/
|
121
|
+
- lib/asca/rest/provisioning/bundleids.rb
|
122
|
+
- lib/asca/rest/provisioning/certificates.rb
|
123
|
+
- lib/asca/rest/provisioning/devices.rb
|
124
|
+
- lib/asca/rest/provisioning/profiles.rb
|
125
|
+
- lib/asca/tools/configuration.rb
|
126
|
+
- lib/asca/tools/log.rb
|
127
|
+
- lib/asca/tools/token.rb
|
128
|
+
- lib/asca/tools/tools.rb
|
123
129
|
- lib/asca/version.rb
|
124
130
|
homepage: https://github.com/xueminghao/appstoreconnectapi
|
125
131
|
licenses:
|
data/lib/asca/configuration.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
module Asca
|
5
|
-
class Configuration
|
6
|
-
ROOTDIR = File.expand_path '~/.com.hurryup.asca'
|
7
|
-
JSONFILE = File.expand_path 'config.json', ROOTDIR
|
8
|
-
CACHE_DIR = File.expand_path 'cache', ROOTDIR
|
9
|
-
class << self
|
10
|
-
# reset config file
|
11
|
-
def reset_config
|
12
|
-
# remove all
|
13
|
-
FileUtils.rm_rf(ROOTDIR)
|
14
|
-
|
15
|
-
# create root dir
|
16
|
-
Dir.mkdir ROOTDIR
|
17
|
-
|
18
|
-
# create cache dir
|
19
|
-
Dir.mkdir CACHE_DIR
|
20
|
-
|
21
|
-
# init config file
|
22
|
-
File.open(JSONFILE, 'w') { |file|
|
23
|
-
file.write("{}")
|
24
|
-
}
|
25
|
-
end
|
26
|
-
|
27
|
-
# update config
|
28
|
-
def update_config(key, value)
|
29
|
-
if !File.exist?(JSONFILE)
|
30
|
-
reset_config
|
31
|
-
end
|
32
|
-
file_content = File.read(JSONFILE)
|
33
|
-
configuration = JSON.parse(file_content)
|
34
|
-
if value
|
35
|
-
configuration[key] = value
|
36
|
-
else
|
37
|
-
configuration.delete(key)
|
38
|
-
end
|
39
|
-
File.open(JSONFILE, 'w') { |file|
|
40
|
-
file.write(JSON.pretty_generate(configuration))
|
41
|
-
}
|
42
|
-
return 0
|
43
|
-
end
|
44
|
-
|
45
|
-
def get_config(key)
|
46
|
-
if !File.exist?(JSONFILE)
|
47
|
-
reset_config
|
48
|
-
end
|
49
|
-
file_content = File.read(JSONFILE)
|
50
|
-
configuration = JSON.parse(file_content)
|
51
|
-
return configuration[key]
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
data/lib/asca/profiles.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'curb'
|
2
|
-
require 'json'
|
3
|
-
require "base64"
|
4
|
-
|
5
|
-
module Asca
|
6
|
-
class Profiles
|
7
|
-
class << self
|
8
|
-
def download_profile(profile_name, out_put_dir = nil)
|
9
|
-
if !out_put_dir
|
10
|
-
out_put_dir = Asca::Configuration.get_config('out_put_dir')
|
11
|
-
if !out_put_dir
|
12
|
-
puts "Please enter your out put dir:"
|
13
|
-
out_put_dir = File.expand_path(gets.chomp)
|
14
|
-
Asca::Configuration.update_config('out_put_dir', out_put_dir)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
http = Curl.get(URI_PROFILES, { 'filter[name]' => profile_name}) do |http|
|
18
|
-
http.headers['Authorization'] = ' Bearer ' + Asca::Token.new_token
|
19
|
-
end
|
20
|
-
profile_obj = JSON.parse(http.body_str)
|
21
|
-
profile_content = profile_obj["data"][0]["attributes"]['profileContent']
|
22
|
-
File.open(File.expand_path(profile_name + ".mobileprovision", out_put_dir), 'w') do |file|
|
23
|
-
file.write(Base64.decode64(profile_content))
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def install_profile(profile_name)
|
28
|
-
download_profile profile_name, Asca::Configuration::CACHE_DIR
|
29
|
-
profile_file_path = File.expand_path(profile_name + ".mobileprovision", Asca::Configuration::CACHE_DIR)
|
30
|
-
|
31
|
-
# install profile
|
32
|
-
`open #{profile_file_path}`
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/asca/token.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'jwt'
|
3
|
-
|
4
|
-
module Asca
|
5
|
-
class Token
|
6
|
-
EXPIRE_DURATION = 20 * 60
|
7
|
-
class << self
|
8
|
-
# Generate new jwt token.
|
9
|
-
def new_token
|
10
|
-
# get token from cache
|
11
|
-
token = get_token_from_cache
|
12
|
-
if token
|
13
|
-
return token
|
14
|
-
end
|
15
|
-
|
16
|
-
# get kid
|
17
|
-
kid = Asca::Configuration.get_config('kid')
|
18
|
-
if !kid
|
19
|
-
puts "Before generating a jwt token, please enter your kid:"
|
20
|
-
kid = gets.chomp
|
21
|
-
Asca::Configuration.update_config('kid', kid)
|
22
|
-
end
|
23
|
-
if !kid
|
24
|
-
puts "Error: no kid!"
|
25
|
-
return
|
26
|
-
end
|
27
|
-
|
28
|
-
# get issuer id
|
29
|
-
iss = Asca::Configuration.get_config('iss')
|
30
|
-
if !iss
|
31
|
-
puts "Before generating a jwt token, please enter your issuer id:"
|
32
|
-
iss = gets.chomp
|
33
|
-
Asca::Configuration.update_config('iss', iss)
|
34
|
-
end
|
35
|
-
if !iss
|
36
|
-
puts "Error: no issuer id!"
|
37
|
-
return
|
38
|
-
end
|
39
|
-
|
40
|
-
# get private key
|
41
|
-
private_key = Asca::Configuration.get_config('private_key')
|
42
|
-
if !private_key
|
43
|
-
puts "Before generating a jwt token, please enter your private key path:"
|
44
|
-
private_key_path = gets.chomp
|
45
|
-
private_key = File.read private_key_path
|
46
|
-
Asca::Configuration.update_config('private_key', private_key)
|
47
|
-
end
|
48
|
-
if !private_key
|
49
|
-
puts "Error: no private key!"
|
50
|
-
return
|
51
|
-
end
|
52
|
-
|
53
|
-
# generate jwt header
|
54
|
-
jwt_header = {
|
55
|
-
"alg": "ES256",
|
56
|
-
"kid": kid,
|
57
|
-
"typ": "JWT"
|
58
|
-
}
|
59
|
-
|
60
|
-
# generate jwt payload
|
61
|
-
exp = Time.now.to_i + EXPIRE_DURATION
|
62
|
-
jwt_payload = {
|
63
|
-
"iss": iss,
|
64
|
-
"exp": exp,
|
65
|
-
"aud": "appstoreconnect-v1"
|
66
|
-
}
|
67
|
-
|
68
|
-
es_key = OpenSSL::PKey::EC.new private_key
|
69
|
-
|
70
|
-
token = JWT.encode jwt_payload, es_key, 'ES256', jwt_header
|
71
|
-
Asca::Configuration.update_config('cache_token_time', exp)
|
72
|
-
Asca::Configuration.update_config('cache_token', token)
|
73
|
-
puts "==== New token generated ===="
|
74
|
-
puts token
|
75
|
-
puts "============================="
|
76
|
-
return token
|
77
|
-
end
|
78
|
-
|
79
|
-
def get_token_from_cache
|
80
|
-
cached_token_time = Asca::Configuration.get_config('cache_token_time')
|
81
|
-
if !cached_token_time
|
82
|
-
return nil
|
83
|
-
end
|
84
|
-
current = Time.now.to_i
|
85
|
-
if cached_token_time - current > EXPIRE_DURATION
|
86
|
-
return nil
|
87
|
-
end
|
88
|
-
return Asca::Configuration.get_config('cache_token')
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|