spaceship 0.3.4 → 0.4.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.
@@ -0,0 +1,77 @@
1
+ module Spaceship
2
+ module Portal
3
+ # Represents an app group of the Apple Dev Portal
4
+ class AppGroup < PortalBase
5
+ # @return (String) The identifier assigned to this group
6
+ # @example
7
+ # "group.com.example.application"
8
+ attr_accessor :group_id
9
+
10
+ # @return (String) The prefix assigned to this group
11
+ # @example
12
+ # "9J57U9392R"
13
+ attr_accessor :prefix
14
+
15
+ # @return (String) The name of this group
16
+ # @example
17
+ # "App Group"
18
+ attr_accessor :name
19
+
20
+ # @return (String) Status of the group
21
+ # @example
22
+ # "current"
23
+ attr_accessor :status
24
+
25
+ # @return (String) The identifier of this app group, provided by the Dev Portal
26
+ # @example
27
+ # "2MAY7NPHAA"
28
+ attr_accessor :app_group_id
29
+
30
+ attr_mapping(
31
+ 'applicationGroup' => :app_group_id,
32
+ 'name' => :name,
33
+ 'prefix' => :prefix,
34
+ 'identifier' => :group_id,
35
+ 'status' => :status
36
+ )
37
+
38
+ class << self
39
+ # Create a new object based on a hash.
40
+ # This is used to create a new object based on the server response.
41
+ def factory(attrs)
42
+ self.new(attrs)
43
+ end
44
+
45
+ # @return (Array) Returns all app groups available for this account
46
+ def all
47
+ client.app_groups.map { |group| self.factory(group) }
48
+ end
49
+
50
+ # Creates a new App Group on the Apple Dev Portal
51
+ #
52
+ # @param group_id [String] the identifier to assign to this group
53
+ # @param name [String] the name of the group
54
+ # @return (AppGroup) The group you just created
55
+ def create!(group_id: nil, name: nil)
56
+ new_group = client.create_app_group!(name, group_id)
57
+ self.new(new_group)
58
+ end
59
+
60
+ # Find a specific App Group group_id
61
+ # @return (AppGroup) The app group you're looking for. This is nil if the app group can't be found.
62
+ def find(group_id)
63
+ all.find do |group|
64
+ group.group_id == group_id
65
+ end
66
+ end
67
+ end
68
+
69
+ # Delete this app group
70
+ # @return (AppGroup) The app group you just deletd
71
+ def delete!
72
+ client.delete_app_group!(app_group_id)
73
+ self
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,222 @@
1
+ module Spaceship
2
+ module Portal
3
+ # Represents a single application service (its state to be more precise) on the Apple Dev Portal
4
+ class AppService
5
+ # @return (String) The identifier used by the Dev Portal to represent this service
6
+ # @example
7
+ # "homeKit"
8
+ attr_accessor :service_id
9
+
10
+ # @return (Object) The current value for this service
11
+ # @example
12
+ # false
13
+ attr_accessor :value
14
+
15
+ # @return (String) The service URI for this service
16
+ # @example
17
+ # "account/ios/identifiers/updateService.action"
18
+ attr_accessor :service_uri
19
+
20
+ def initialize(service_id, value)
21
+ @service_id = service_id
22
+ @value = value
23
+
24
+ if @service_id == "push"
25
+ # Push notifications have a special URI
26
+ @service_uri = "account/ios/identifiers/updatePushService.action"
27
+ else
28
+ # Default service URI
29
+ @service_uri = "account/ios/identifiers/updateService.action"
30
+ end
31
+ end
32
+
33
+ class << self
34
+ def app_group
35
+ self::AppGroup
36
+ end
37
+
38
+ def associated_domains
39
+ self::AssociatedDomains
40
+ end
41
+
42
+ def data_protection
43
+ self::DataProtection
44
+ end
45
+
46
+ def health_kit
47
+ self::HealthKit
48
+ end
49
+
50
+ def home_kit
51
+ self::HomeKit
52
+ end
53
+
54
+ def wireless_accessory
55
+ self::WirelessAccessory
56
+ end
57
+
58
+ def icloud
59
+ self::Cloud
60
+ end
61
+
62
+ def cloud_kit
63
+ self::CloudKit
64
+ end
65
+
66
+ def inter_app_audio
67
+ self::InterAppAudio
68
+ end
69
+
70
+ def passbook
71
+ self::Passbook
72
+ end
73
+
74
+ def push_notification
75
+ self::PushNotification
76
+ end
77
+
78
+ def vpn_configuration
79
+ self::VPNConfiguration
80
+ end
81
+ end
82
+
83
+ def ==(other)
84
+ self.class == other.class &&
85
+ self.service_id == other.service_id &&
86
+ self.value == other.value &&
87
+ self.service_uri == other.service_uri
88
+ end
89
+
90
+ #
91
+ # Modules for "constants"
92
+ #
93
+ module AppGroup
94
+ def self.off
95
+ AppService.new("APG3427HIY", false)
96
+ end
97
+
98
+ def self.on
99
+ AppService.new("APG3427HIY", true)
100
+ end
101
+ end
102
+
103
+ module AssociatedDomains
104
+ def self.off
105
+ AppService.new("SKC3T5S89Y", false)
106
+ end
107
+
108
+ def self.on
109
+ AppService.new("SKC3T5S89Y", true)
110
+ end
111
+ end
112
+
113
+ module DataProtection
114
+ def self.off
115
+ AppService.new("dataProtection", "")
116
+ end
117
+
118
+ def self.complete
119
+ AppService.new("dataProtection", "complete")
120
+ end
121
+
122
+ def self.unless_open
123
+ AppService.new("dataProtection", "unlessopen")
124
+ end
125
+
126
+ def self.until_first_auth
127
+ AppService.new("dataProtection", "untilfirstauth")
128
+ end
129
+ end
130
+
131
+ module HealthKit
132
+ def self.off
133
+ AppService.new("HK421J6T7P", false)
134
+ end
135
+
136
+ def self.on
137
+ AppService.new("HK421J6T7P", true)
138
+ end
139
+ end
140
+
141
+ module HomeKit
142
+ def self.off
143
+ AppService.new("homeKit", false)
144
+ end
145
+
146
+ def self.on
147
+ AppService.new("homeKit", true)
148
+ end
149
+ end
150
+
151
+ module WirelessAccessory
152
+ def self.off
153
+ AppService.new("WC421J6T7P", false)
154
+ end
155
+
156
+ def self.on
157
+ AppService.new("WC421J6T7P", true)
158
+ end
159
+ end
160
+
161
+ module Cloud
162
+ def self.off
163
+ AppService.new("iCloud", false)
164
+ end
165
+
166
+ def self.on
167
+ AppService.new("iCloud", true)
168
+ end
169
+ end
170
+
171
+ module CloudKit
172
+ def self.xcode5_compatible
173
+ AppService.new("cloudKitVersion", 1)
174
+ end
175
+
176
+ def self.cloud_kit
177
+ AppService.new("cloudKitVersion", 2)
178
+ end
179
+ end
180
+
181
+ module InterAppAudio
182
+ def self.off
183
+ AppService.new("IAD53UNK2F", false)
184
+ end
185
+
186
+ def self.on
187
+ AppService.new("IAD53UNK2F", true)
188
+ end
189
+ end
190
+
191
+ module Passbook
192
+ def self.off
193
+ AppService.new("pass", false)
194
+ end
195
+
196
+ def self.on
197
+ AppService.new("pass", true)
198
+ end
199
+ end
200
+
201
+ module PushNotification
202
+ def self.off
203
+ AppService.new("push", false)
204
+ end
205
+
206
+ def self.on
207
+ AppService.new("push", true)
208
+ end
209
+ end
210
+
211
+ module VPNConfiguration
212
+ def self.off
213
+ AppService.new("V66P55NK2I", false)
214
+ end
215
+
216
+ def self.on
217
+ AppService.new("V66P55NK2I", true)
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
@@ -237,7 +237,7 @@ module Spaceship
237
237
  end
238
238
 
239
239
  # ensure csr is a OpenSSL::X509::Request
240
- csr = OpenSSL::X509::Request.new(csr) if csr.is_a?(String)
240
+ csr = OpenSSL::X509::Request.new(csr) if csr.kind_of?(String)
241
241
 
242
242
  # if this succeeds, we need to save the .cer and the private key in keychain access or wherever they go in linux
243
243
  response = client.create_certificate!(type, csr.to_pem, app_id)
@@ -266,7 +266,7 @@ module Spaceship
266
266
 
267
267
  # @return (Bool): Is this certificate a push profile for apps?
268
268
  def is_push?
269
- self.kind_of?PushCertificate
269
+ self.kind_of? PushCertificate
270
270
  end
271
271
  end
272
272
  end
@@ -3,27 +3,27 @@ module Spaceship
3
3
  # Represents a device from the Apple Developer Portal
4
4
  class Device < PortalBase
5
5
  # @return (String) The ID given from the developer portal. You'll probably not need it.
6
- # @example
6
+ # @example
7
7
  # "XJXGVS46MW"
8
8
  attr_accessor :id
9
9
 
10
10
  # @return (String) The name of the device
11
- # @example
11
+ # @example
12
12
  # "Felix Krause's iPhone 6"
13
13
  attr_accessor :name
14
14
 
15
15
  # @return (String) The UDID of the device
16
- # @example
16
+ # @example
17
17
  # "4c24a7ee5caaa4847f49aaab2d87483053f53b65"
18
18
  attr_accessor :udid
19
19
 
20
20
  # @return (String) The platform of the device. This is probably always "ios"
21
- # @example
21
+ # @example
22
22
  # "ios"
23
23
  attr_accessor :platform
24
24
 
25
25
  # @return (String) Status of the device. Probably always "c"
26
- # @example
26
+ # @example
27
27
  # "c"
28
28
  attr_accessor :status
29
29
 
@@ -47,7 +47,7 @@ module Spaceship
47
47
  client.devices.map { |device| self.factory(device) }
48
48
  end
49
49
 
50
- # @return (Device) Find a device based on the ID of the device. *Attention*:
50
+ # @return (Device) Find a device based on the ID of the device. *Attention*:
51
51
  # This is *not* the UDID. nil if no device was found.
52
52
  def find(device_id)
53
53
  all.find do |device|
@@ -72,7 +72,7 @@ module Spaceship
72
72
  # Register a new device to this account
73
73
  # @param name (String) (required): The name of the new device
74
74
  # @param udid (String) (required): The UDID of the new device
75
- # @example
75
+ # @example
76
76
  # Spaceship.device.create!(name: "Felix Krause's iPhone 6", udid: "4c24a7ee5caaa4847f49aaab2d87483053f53b65")
77
77
  # @return (Device): The newly created device
78
78
  def create!(name: nil, udid: nil)
@@ -1,6 +1,8 @@
1
1
  require 'spaceship/portal/portal_base'
2
2
  require 'spaceship/portal/app'
3
+ require 'spaceship/portal/app_group'
4
+ require 'spaceship/portal/app_service'
3
5
  require 'spaceship/portal/certificate'
4
6
  require 'spaceship/portal/device'
5
7
  require 'spaceship/portal/provisioning_profile'
6
- require 'spaceship/portal/portal_client'
8
+ require 'spaceship/portal/portal_client'
@@ -10,4 +10,4 @@ module Spaceship
10
10
  end
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -13,7 +13,7 @@ module Spaceship
13
13
  def api_key
14
14
  cache_path = "/tmp/spaceship_api_key.txt"
15
15
  begin
16
- cached = File.read(cache_path)
16
+ cached = File.read(cache_path)
17
17
  rescue Errno::ENOENT
18
18
  end
19
19
  return cached if cached
@@ -87,7 +87,6 @@ module Spaceship
87
87
  @in_house = (team_information['type'] == 'In-House')
88
88
  end
89
89
 
90
-
91
90
  #####################################################
92
91
  # @!group Apps
93
92
  #####################################################
@@ -112,6 +111,28 @@ module Spaceship
112
111
  parse_response(r, 'appId')
113
112
  end
114
113
 
114
+ def update_service_for_app(app, service)
115
+ request(:post, service.service_uri, {
116
+ teamId: team_id,
117
+ displayId: app.app_id,
118
+ featureType: service.service_id,
119
+ featureValue: service.value
120
+ })
121
+
122
+ details_for_app(app)
123
+ end
124
+
125
+ def associate_groups_with_app(app, groups)
126
+ r = request(:post, 'account/ios/identifiers/assignApplicationGroupToAppId.action', {
127
+ teamId: team_id,
128
+ appIdId: app.app_id,
129
+ displayId: app.app_id,
130
+ applicationGroups: groups.map { |g| g.app_group_id }
131
+ })
132
+
133
+ details_for_app(app)
134
+ end
135
+
115
136
  def create_app!(type, name, bundle_id)
116
137
  ident_params = case type.to_sym
117
138
  when :explicit
@@ -150,6 +171,39 @@ module Spaceship
150
171
  parse_response(r)
151
172
  end
152
173
 
174
+ #####################################################
175
+ # @!group App Groups
176
+ #####################################################
177
+
178
+ def app_groups
179
+ paging do |page_number|
180
+ r = request(:post, 'account/ios/identifiers/listApplicationGroups.action', {
181
+ teamId: team_id,
182
+ pageNumber: page_number,
183
+ pageSize: page_size,
184
+ sort: 'name=asc'
185
+ })
186
+ parse_response(r, 'applicationGroupList')
187
+ end
188
+ end
189
+
190
+ def create_app_group!(name, group_id)
191
+ r = request(:post, 'account/ios/identifiers/addApplicationGroup.action', {
192
+ name: name,
193
+ identifier: group_id,
194
+ teamId: team_id
195
+ })
196
+ parse_response(r, 'applicationGroup')
197
+ end
198
+
199
+ def delete_app_group!(app_group_id)
200
+ r = request(:post, 'account/ios/identifiers/deleteApplicationGroup.action', {
201
+ teamId: team_id,
202
+ applicationGroup: app_group_id
203
+ })
204
+ parse_response(r)
205
+ end
206
+
153
207
  #####################################################
154
208
  # @!group Devices
155
209
  #####################################################
@@ -167,7 +221,7 @@ module Spaceship
167
221
  end
168
222
 
169
223
  def create_device!(device_name, device_id)
170
- r = request(:post) do |r|
224
+ req = request(:post) do |r|
171
225
  r.url "https://developerservices2.apple.com/services/#{PROTOCOL_VERSION}/ios/addDevice.action"
172
226
  r.params = {
173
227
  teamId: team_id,
@@ -176,7 +230,7 @@ module Spaceship
176
230
  }
177
231
  end
178
232
 
179
- parse_response(r, 'device')
233
+ parse_response(req, 'device')
180
234
  end
181
235
 
182
236
  #####################################################
@@ -201,7 +255,7 @@ module Spaceship
201
255
  teamId: team_id,
202
256
  type: type,
203
257
  csrContent: csr,
204
- appIdId: app_id #optional
258
+ appIdId: app_id # optional
205
259
  })
206
260
  parse_response(r, 'certRequest')
207
261
  end
@@ -231,16 +285,16 @@ module Spaceship
231
285
  #####################################################
232
286
 
233
287
  def provisioning_profiles
234
- r = request(:post) do |r|
288
+ req = request(:post) do |r|
235
289
  r.url "https://developerservices2.apple.com/services/#{PROTOCOL_VERSION}/ios/listProvisioningProfiles.action"
236
290
  r.params = {
237
291
  teamId: team_id,
238
292
  includeInactiveProfiles: true,
239
- onlyCountLists: true,
293
+ onlyCountLists: true
240
294
  }
241
295
  end
242
296
 
243
- parse_response(r, 'provisioningProfiles')
297
+ parse_response(req, 'provisioningProfiles')
244
298
  end
245
299
 
246
300
  def create_provisioning_profile!(name, distribution_method, app_id, certificate_ids, device_ids)
@@ -278,11 +332,11 @@ module Spaceship
278
332
  provisioningProfileName: name,
279
333
  appIdId: app_id,
280
334
  distributionType: distribution_method,
281
- certificateIds: certificate_ids.first, # we are most of the times only allowed to pass one
335
+ certificateIds: certificate_ids.join(','),
282
336
  deviceIds: device_ids
283
337
  })
284
338
 
285
339
  parse_response(r, 'provisioningProfile')
286
340
  end
287
341
  end
288
- end
342
+ end