asca 0.1.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Asca
2
- VERSION = "0.1.2"
2
+ VERSION = "1.0.0"
3
3
  end
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: 0.1.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - xueminghao
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-19 00:00:00.000000000 Z
11
+ date: 2020-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -111,16 +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/log.rb
122
- - lib/asca/profiles.rb
123
- - lib/asca/token.rb
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
124
129
  - lib/asca/version.rb
125
130
  homepage: https://github.com/xueminghao/appstoreconnectapi
126
131
  licenses:
@@ -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
@@ -1,53 +0,0 @@
1
- module Asca
2
- class Log
3
- class Color
4
- class << self
5
- def time
6
- "\e[37m"
7
- end
8
-
9
- def warn
10
- "\e[33;1m"
11
- end
12
-
13
- def info
14
- "\e[32m"
15
- end
16
-
17
- def error
18
- "\e[31;1m"
19
- end
20
-
21
- def reset
22
- "\e[0m"
23
- end
24
-
25
- def command
26
- "\e[34m"
27
- end
28
- end
29
- end
30
-
31
- class << self
32
- def warn message
33
- puts "#{Color.warn}WARN: #{message}#{Color.reset}"
34
- end
35
-
36
- def info message
37
- puts "#{Color.info}INFO: #{message}#{Color.reset}"
38
- end
39
-
40
- def error message
41
- puts "#{Color.error}ERROR: #{message}#{Color.reset}", STDERR
42
- end
43
-
44
- def command message
45
- puts "#{Color.command}RUN: \e[4m#{message}#{Color.reset}"
46
- end
47
-
48
- def puts message, io = STDOUT
49
- io.puts "#{Color.time}[#{Time.new}]#{Color.reset} #{message}"
50
- end
51
- end
52
- end
53
- end
@@ -1,38 +0,0 @@
1
- require 'http'
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
- response = HTTP.auth('Bearer ' + Asca::Token.new_token).get(URI_PROFILES, :params => { 'filter[name]' => profile_name })
18
- if response.status.success?
19
- profile_obj = JSON.parse(response.body)
20
- profile_content = profile_obj["data"][0]["attributes"]['profileContent']
21
- File.open(File.expand_path(profile_name + ".mobileprovision", out_put_dir), 'w') do |file|
22
- file.write(Base64.decode64(profile_content))
23
- end
24
- else
25
- Log.error(response.body)
26
- end
27
- end
28
-
29
- def install_profile(profile_name)
30
- download_profile profile_name, Asca::Configuration::CACHE_DIR
31
- profile_file_path = File.expand_path(profile_name + ".mobileprovision", Asca::Configuration::CACHE_DIR)
32
-
33
- # install profile
34
- `open #{profile_file_path}`
35
- end
36
- end
37
- end
38
- end
@@ -1,100 +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
- Asca::Log.info "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
- Asca::Log.error "Error: no kid!"
25
- return
26
- end
27
-
28
- # get issuer id
29
- iss = Asca::Configuration.get_config('iss')
30
- if !iss
31
- Asca::Log.info "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
- Asca::Log.error "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
- Asca::Log.info "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
- Asca::Log.error "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
- begin
69
- es_key = OpenSSL::PKey::EC.new private_key
70
- rescue => exception
71
- Asca::Log.info "Invalid private key, please enter your correct private key path:"
72
- private_key_path = gets.chomp
73
- private_key = File.read private_key_path
74
- Asca::Configuration.update_config('private_key', private_key)
75
- es_key = OpenSSL::PKey::EC.new private_key
76
- end
77
-
78
- token = JWT.encode jwt_payload, es_key, 'ES256', jwt_header
79
- Asca::Configuration.update_config('cache_token_time', exp)
80
- Asca::Configuration.update_config('cache_token', token)
81
- Asca::Log.info "==== New token generated ===="
82
- Asca::Log.info token
83
- Asca::Log.info "============================="
84
- return token
85
- end
86
-
87
- def get_token_from_cache
88
- token_valid_max_time = Asca::Configuration.get_config('cache_token_time')
89
- if !token_valid_max_time
90
- return nil
91
- end
92
- current = Time.now.to_i
93
- if token_valid_max_time > current
94
- return Asca::Configuration.get_config('cache_token')
95
- end
96
- return nil
97
- end
98
- end
99
- end
100
- end