spaceship 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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