apple_class_client 0.0.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/README.md +4 -0
- data/apple_class_client.gemspec +4 -2
- data/lib/apple_class_client.rb +6 -1
- data/lib/apple_class_client/auth.rb +51 -0
- data/lib/apple_class_client/configuration.rb +44 -0
- data/lib/apple_class_client/error.rb +47 -0
- data/lib/apple_class_client/hacks/typhoeus_request.rb +57 -0
- data/lib/apple_class_client/request.rb +41 -0
- data/lib/apple_class_client/version.rb +1 -1
- metadata +46 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf5ca3c450a74dc4dbf1f8cd9b09b6ce72ca48e8
|
4
|
+
data.tar.gz: 1f416edf07f9f13a9142616b22b85c3580427e38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e12f5ff91b5812b61bc4e234f8dab2a377fa26b7cb5492c5dd5c607a0e4aae0e6e72fa5f21ee67b7717fa291e48cdf0efc182dc9e9a6cbc0572e20220dd122f3
|
7
|
+
data.tar.gz: 1c4a46b7b2f31a6f483941b8a9447031244eca2414d157ad27a02f91a38aa47ffe71f6cb6400ba81999d433dbe71c02574a154a67f67a05d730da0c19252ea09
|
data/CHANGELOG.md
CHANGED
data/CODE_OF_CONDUCT.md
CHANGED
@@ -35,7 +35,7 @@ This code of conduct applies both within project spaces and in public spaces
|
|
35
35
|
when an individual is representing the project or its community.
|
36
36
|
|
37
37
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
-
reported by contacting a project maintainer at
|
38
|
+
reported by contacting a project maintainer at aywang31@gmail.com. All
|
39
39
|
complaints will be reviewed and investigated and will result in a response that
|
40
40
|
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
41
|
obligated to maintain confidentiality with regard to the reporter of an
|
data/README.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# AppleClassClient
|
2
2
|
|
3
|
+
[ ![Codeship Status for albertyw/apple_class_client](https://app.codeship.com/projects/9c364080-fd10-0133-688f-7e176884dbc2/status?branch=master)](https://app.codeship.com/projects/152119)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/albertyw/apple_class_client/badges/gpa.svg)](https://codeclimate.com/github/albertyw/apple_class_client)
|
5
|
+
[![Dependency Status](https://gemnasium.com/badges/github.com/albertyw/apple_class_client.svg)](https://gemnasium.com/github.com/albertyw/apple_class_client)
|
6
|
+
|
3
7
|
This is a client for accessing Apple MDM's class, person, location, and course rosters.
|
4
8
|
|
5
9
|
## Installation
|
data/apple_class_client.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "apple_class_client"
|
8
8
|
spec.version = AppleClassClient::VERSION
|
9
9
|
spec.authors = ["Albert Wang"]
|
10
|
-
spec.email = ["
|
10
|
+
spec.email = ["aywang31@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{Client for accessing Apple MDM class information}
|
13
13
|
spec.description = %q{This is a client for accessing Apple MDM's class, person, location, and course rosters.}
|
@@ -19,7 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
+
spec.add_dependency "oauth", "~> 0.4"
|
23
|
+
spec.add_dependency "typhoeus", [">= 0.7", "< 1.2"]
|
22
24
|
spec.add_development_dependency "bundler", "~> 1.12"
|
23
|
-
spec.add_development_dependency "rake", "
|
25
|
+
spec.add_development_dependency "rake", ">= 11.0"
|
24
26
|
spec.add_development_dependency "rspec", "~> 3.0"
|
25
27
|
end
|
data/lib/apple_class_client.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
require "apple_class_client/version"
|
2
|
+
require "apple_class_client/configuration"
|
2
3
|
|
3
4
|
module AppleClassClient
|
4
|
-
|
5
|
+
extend Configuration
|
5
6
|
end
|
7
|
+
|
8
|
+
require "apple_class_client/auth"
|
9
|
+
require "apple_class_client/error"
|
10
|
+
require "apple_class_client/request"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Apple Session Authorization Token management
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "oauth"
|
5
|
+
require File.join(File.dirname(__FILE__), "hacks", "typhoeus_request")
|
6
|
+
require "securerandom"
|
7
|
+
require "typhoeus"
|
8
|
+
|
9
|
+
module AppleClassClient
|
10
|
+
module Auth
|
11
|
+
# Apple requires a quirky OAuth 1.0a authentication to get a temporary
|
12
|
+
# X-ADM-Auth-Session key to make requests; this takes care of that
|
13
|
+
|
14
|
+
OAUTH_PATH = "/session"
|
15
|
+
|
16
|
+
def self.get_session_token
|
17
|
+
options = { method: :get, headers: AppleClassClient::Request::DEFAULT_HEADERS }
|
18
|
+
request = Typhoeus::Request.new(AppleClassClient::Request.make_url(OAUTH_PATH), options)
|
19
|
+
request.options[:headers].merge!({ "Authorization" => oauth_header(request) })
|
20
|
+
request.run
|
21
|
+
response = request.response
|
22
|
+
AppleClassClient::Error.check_request_error(response, auth: true)
|
23
|
+
parse_response response
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.oauth_header(request)
|
27
|
+
consumer = OAuth::Consumer.new(
|
28
|
+
AppleClassClient.consumer_key,
|
29
|
+
AppleClassClient.consumer_secret,
|
30
|
+
site: AppleClassClient::Request.make_url(OAUTH_PATH),
|
31
|
+
)
|
32
|
+
token = OAuth::AccessToken.new(
|
33
|
+
consumer,
|
34
|
+
AppleClassClient.access_token,
|
35
|
+
AppleClassClient.access_secret,
|
36
|
+
)
|
37
|
+
oauth_params = {
|
38
|
+
consumer: consumer,
|
39
|
+
realm: "ADM",
|
40
|
+
token: token,
|
41
|
+
}
|
42
|
+
oauth_helper = OAuth::Client::Helper.new request, oauth_params.merge(request_uri: AppleClassClient::Request.make_url(OAUTH_PATH))
|
43
|
+
oauth_helper.header
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.parse_response(response)
|
47
|
+
body = JSON.parse response.response_body
|
48
|
+
auth_session_token = body["auth_session_token"]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Configuration for AppleClassClient
|
2
|
+
# Configuration values can be either literals or Procs; note that Procs will not
|
3
|
+
# be overwritten by AppleClassClient::Token.save_data
|
4
|
+
|
5
|
+
module AppleClassClient
|
6
|
+
module Configuration
|
7
|
+
CONFIG = {
|
8
|
+
private_key: nil, # MDM Server's private key for decrypting token files
|
9
|
+
consumer_key: nil, # Server Token information
|
10
|
+
consumer_secret: nil,
|
11
|
+
access_token: nil,
|
12
|
+
access_secret: nil,
|
13
|
+
access_token_expiry: nil,
|
14
|
+
apple_mdm_server: "https://mdmenrollment.apple.com", # Apple MDM server url
|
15
|
+
user_agent: "CellabusMDM",
|
16
|
+
}
|
17
|
+
|
18
|
+
CONFIG.freeze
|
19
|
+
|
20
|
+
attr_writer *CONFIG.keys
|
21
|
+
|
22
|
+
def method_missing(m, *_args, &_block)
|
23
|
+
if CONFIG.keys.include? m.to_sym
|
24
|
+
get_value(m)
|
25
|
+
else
|
26
|
+
raise NoMethodError, "Unknown method #{m}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_value(m)
|
31
|
+
value = instance_variable_get("@#{m}")
|
32
|
+
value = get_default_value(m) if value.nil?
|
33
|
+
(value.is_a? Proc) ? value.call : value
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_default_value(key)
|
37
|
+
CONFIG[key.to_sym]
|
38
|
+
end
|
39
|
+
|
40
|
+
def configure
|
41
|
+
yield self
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Errors for AppleClassClient and Apple's endpoints
|
2
|
+
|
3
|
+
require 'typhoeus'
|
4
|
+
|
5
|
+
module AppleClassClient
|
6
|
+
module Error
|
7
|
+
AUTH_ERRORS = [
|
8
|
+
# Used by AppleClassClient::Auth
|
9
|
+
["BadRequest", 400, ""],
|
10
|
+
["Unauthorized", 401, ""],
|
11
|
+
["Forbidden", 403, ""],
|
12
|
+
]
|
13
|
+
|
14
|
+
ERRORS = [
|
15
|
+
# Server failures
|
16
|
+
["InternalServerError", 500, ""],
|
17
|
+
["ServiceUnavailable", 503, ""],
|
18
|
+
|
19
|
+
# Client errors
|
20
|
+
["Unauthorized", 401, "UNAUTHORIZED"],
|
21
|
+
["Forbidden", 403, "FORBIDDEN"],
|
22
|
+
["MalformedRequest", 400, "MALFORMED_REQUEST_BODY"],
|
23
|
+
["CursorRequired", 400, "CURSOR_REQUIRED"],
|
24
|
+
["InvalidCursor", 400, "INVALID_CURSOR"],
|
25
|
+
["ExpiredCursor", 400, "EXPIRED_CURSOR"],
|
26
|
+
["TooManyRequests", 429, "TOO_MANY_REQUESTS"],
|
27
|
+
]
|
28
|
+
|
29
|
+
def self.check_request_error(response, auth:false)
|
30
|
+
get_errors(auth: auth).each do |error_name, response_code, body|
|
31
|
+
if response.code == response_code && response.body.include?(body)
|
32
|
+
raise RequestError, error_name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
if response.code != 200
|
36
|
+
raise RequestError, "GenericError"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.get_errors(auth:false)
|
41
|
+
auth ? AUTH_ERRORS : ERRORS
|
42
|
+
end
|
43
|
+
|
44
|
+
class RequestError < RuntimeError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# This contains a few hacks that adds support for non-ancient versions of Typhoeus to
|
2
|
+
# the ancient dead ruby oauth gem
|
3
|
+
|
4
|
+
require "oauth/request_proxy/base"
|
5
|
+
require "typhoeus"
|
6
|
+
require "typhoeus/request"
|
7
|
+
require "uri"
|
8
|
+
require "cgi"
|
9
|
+
|
10
|
+
module OAuth::RequestProxy::Typhoeus
|
11
|
+
class Request < OAuth::RequestProxy::Base
|
12
|
+
# Proxy for signing Typhoeus::Request requests
|
13
|
+
# Usage example:
|
14
|
+
# oauth_params = {:consumer => oauth_consumer, :token => access_token}
|
15
|
+
# req = Typhoeus::Request.new(uri, options)
|
16
|
+
# oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => uri))
|
17
|
+
# req.headers.merge!({"Authorization" => oauth_helper.header})
|
18
|
+
# hydra = Typhoeus::Hydra.new()
|
19
|
+
# hydra.queue(req)
|
20
|
+
# hydra.run
|
21
|
+
# response = req.response
|
22
|
+
proxies Typhoeus::Request
|
23
|
+
|
24
|
+
def method
|
25
|
+
request_method = request.options[:method].to_s.upcase
|
26
|
+
request_method.empty? ? "GET" : request_method
|
27
|
+
end
|
28
|
+
|
29
|
+
def uri
|
30
|
+
options[:uri].to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def parameters
|
34
|
+
if options[:clobber_request]
|
35
|
+
options[:parameters]
|
36
|
+
else
|
37
|
+
post_parameters.merge(query_parameters).merge(options[:parameters] || {})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def query_parameters
|
44
|
+
query = URI.parse(request.url).query
|
45
|
+
query ? CGI.parse(query) : {}
|
46
|
+
end
|
47
|
+
|
48
|
+
def post_parameters
|
49
|
+
# Post params are only used if posting form data
|
50
|
+
if method == "POST"
|
51
|
+
OAuth::Helper.stringify_keys(request.params || {})
|
52
|
+
else
|
53
|
+
{}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Wrapper around requests to MDM class endpoint
|
2
|
+
# Will also handle any error conditions
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
require "typhoeus"
|
6
|
+
|
7
|
+
module AppleClassClient
|
8
|
+
module Request
|
9
|
+
DEFAULT_HEADERS = {
|
10
|
+
"User-Agent" => "#{AppleClassClient.user_agent}/#{AppleClassClient::VERSION}",
|
11
|
+
"X-Server-Protocol-Version" => "2",
|
12
|
+
"Content-Type" => "application/json;charset=UTF8",
|
13
|
+
}
|
14
|
+
DEFAULT_HEADERS.freeze
|
15
|
+
|
16
|
+
def self.make_request(url, query_type, body, params:nil, headers:nil)
|
17
|
+
if headers == nil
|
18
|
+
headers = make_headers
|
19
|
+
end
|
20
|
+
request = Typhoeus::Request.new(
|
21
|
+
url,
|
22
|
+
method: query_type,
|
23
|
+
body: body,
|
24
|
+
params: params,
|
25
|
+
headers: headers,
|
26
|
+
)
|
27
|
+
request.run
|
28
|
+
AppleClassClient::Error.check_request_error request.response
|
29
|
+
JSON.parse request.response.body
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.make_headers
|
33
|
+
session_auth_token = AppleClassClient::Auth.get_session_token
|
34
|
+
DEFAULT_HEADERS.merge("X-ADM-Auth-Session" => session_auth_token)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.make_url(path)
|
38
|
+
AppleClassClient.apple_mdm_server + path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,49 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apple_class_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Albert Wang
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: oauth
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: typhoeus
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.7'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '1.2'
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.7'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.2'
|
13
47
|
- !ruby/object:Gem::Dependency
|
14
48
|
name: bundler
|
15
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -28,16 +62,16 @@ dependencies:
|
|
28
62
|
name: rake
|
29
63
|
requirement: !ruby/object:Gem::Requirement
|
30
64
|
requirements:
|
31
|
-
- - "
|
65
|
+
- - ">="
|
32
66
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
67
|
+
version: '11.0'
|
34
68
|
type: :development
|
35
69
|
prerelease: false
|
36
70
|
version_requirements: !ruby/object:Gem::Requirement
|
37
71
|
requirements:
|
38
|
-
- - "
|
72
|
+
- - ">="
|
39
73
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
74
|
+
version: '11.0'
|
41
75
|
- !ruby/object:Gem::Dependency
|
42
76
|
name: rspec
|
43
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -55,7 +89,7 @@ dependencies:
|
|
55
89
|
description: This is a client for accessing Apple MDM's class, person, location, and
|
56
90
|
course rosters.
|
57
91
|
email:
|
58
|
-
-
|
92
|
+
- aywang31@gmail.com
|
59
93
|
executables: []
|
60
94
|
extensions: []
|
61
95
|
extra_rdoc_files: []
|
@@ -71,6 +105,11 @@ files:
|
|
71
105
|
- bin/console
|
72
106
|
- bin/setup
|
73
107
|
- lib/apple_class_client.rb
|
108
|
+
- lib/apple_class_client/auth.rb
|
109
|
+
- lib/apple_class_client/configuration.rb
|
110
|
+
- lib/apple_class_client/error.rb
|
111
|
+
- lib/apple_class_client/hacks/typhoeus_request.rb
|
112
|
+
- lib/apple_class_client/request.rb
|
74
113
|
- lib/apple_class_client/version.rb
|
75
114
|
homepage: https://github.com/albertyw/apple_class_client
|
76
115
|
licenses:
|