antaeus-sdk 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +119 -0
  4. data/bin/antaeus-cli +35 -0
  5. data/lib/antaeus-sdk.rb +58 -0
  6. data/lib/antaeus-sdk/api_client.rb +105 -0
  7. data/lib/antaeus-sdk/api_info.rb +47 -0
  8. data/lib/antaeus-sdk/config.rb +54 -0
  9. data/lib/antaeus-sdk/exception.rb +5 -0
  10. data/lib/antaeus-sdk/exceptions/approval_change_failed.rb +6 -0
  11. data/lib/antaeus-sdk/exceptions/authentication_failure.rb +6 -0
  12. data/lib/antaeus-sdk/exceptions/checkin_change_failed.rb +6 -0
  13. data/lib/antaeus-sdk/exceptions/checkout_change_failed.rb +6 -0
  14. data/lib/antaeus-sdk/exceptions/immutable_instance.rb +6 -0
  15. data/lib/antaeus-sdk/exceptions/immutable_modification.rb +6 -0
  16. data/lib/antaeus-sdk/exceptions/invalid_api_client.rb +6 -0
  17. data/lib/antaeus-sdk/exceptions/invalid_config_data.rb +6 -0
  18. data/lib/antaeus-sdk/exceptions/invalid_entity.rb +6 -0
  19. data/lib/antaeus-sdk/exceptions/invalid_input.rb +6 -0
  20. data/lib/antaeus-sdk/exceptions/invalid_options.rb +6 -0
  21. data/lib/antaeus-sdk/exceptions/invalid_property.rb +6 -0
  22. data/lib/antaeus-sdk/exceptions/invalid_where_query.rb +6 -0
  23. data/lib/antaeus-sdk/exceptions/login_required.rb +6 -0
  24. data/lib/antaeus-sdk/exceptions/missing_api_client.rb +6 -0
  25. data/lib/antaeus-sdk/exceptions/missing_entity.rb +6 -0
  26. data/lib/antaeus-sdk/exceptions/missing_path.rb +6 -0
  27. data/lib/antaeus-sdk/exceptions/new_instance_with_id.rb +6 -0
  28. data/lib/antaeus-sdk/guest_api_client.rb +63 -0
  29. data/lib/antaeus-sdk/helpers/string.rb +24 -0
  30. data/lib/antaeus-sdk/resource.rb +363 -0
  31. data/lib/antaeus-sdk/resource_collection.rb +198 -0
  32. data/lib/antaeus-sdk/resources/appointment.rb +166 -0
  33. data/lib/antaeus-sdk/resources/group.rb +27 -0
  34. data/lib/antaeus-sdk/resources/guest.rb +41 -0
  35. data/lib/antaeus-sdk/resources/hook.rb +17 -0
  36. data/lib/antaeus-sdk/resources/location.rb +50 -0
  37. data/lib/antaeus-sdk/resources/remote_application.rb +13 -0
  38. data/lib/antaeus-sdk/resources/user.rb +28 -0
  39. data/lib/antaeus-sdk/user_api_client.rb +63 -0
  40. data/lib/antaeus-sdk/version.rb +7 -0
  41. metadata +209 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 250a4b2c9a9e103be45ae8f6d28029664db8d8fa
4
+ data.tar.gz: b1aa610aa33a51ec61f79feee4831bb348438558
5
+ SHA512:
6
+ metadata.gz: f3147a11ca8e7b7c3908151b7d2ffcb7799d287c8d79d5cfee7c5c50b06a7fe52c1a975e994eb3739675b20555a5e8b1067ba5e2a1ee6d63a16dece482ea3a68
7
+ data.tar.gz: ea5ff1f4fbfe17642390ea2394267d2ebcaf3554f0d625fbcac6e5b473bfa326bb02bbaee46b2c4c3c71ad990d2dc816f5800c590ae1bd8aa3bb6f960c7d1ad3
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 KnuEdge
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,119 @@
1
+ The Antaeus SDK for Ruby
2
+ ====================
3
+
4
+ About
5
+ ----
6
+ Antaeus is a guest management system written by [KnuEdge](https://www.knuedge.com). The name comes from [a figure in Greek mythology](https://en.wikipedia.org/wiki/Antaeus) that would challenge travellers passing through his land to compete with him in a wrestling match. While this application has little to do with wrestling, it is used to track passers-by at [KnuEdge](https://www.knuedge.com) office locations.
7
+
8
+ This is the Ruby SDK designed to aid in and serve as a reference for interacting with the [Antaeus API](#). This SDK is certainly not required to use the API (everything could be done with `curl` calls or most any REST client), but it provides first-class Ruby objects to make things easy for a Ruby developer. It also happens to serve as the basis for the [Antaeus Web](#) application.
9
+
10
+ Building and Installing
11
+ ----
12
+ Building the gem requires a modern Ruby:
13
+
14
+ # highly recommend using RVM here, and Ruby 2.x or above
15
+ gem build antaeus-sdk.gemspec
16
+ # install what you just built
17
+ gem install antaeus-sdk-*.gem
18
+
19
+ That said, recent releases should be available on [rubygems.org](https://rubygems.org/) so building is probably not necessary.
20
+
21
+ Just add the following to your Gemfile:
22
+
23
+ gem 'antaeus-sdk', '~> 0.2'
24
+
25
+ Then run:
26
+
27
+ bundle install
28
+
29
+ If you're not using [bundler](http://bundler.io/) for some reason (shame on you!), you can manually install like so:
30
+
31
+ gem install antaeus-sdk
32
+
33
+ If you see a message like this:
34
+
35
+ Thanks for installing the Antaeus Ruby SDK!
36
+
37
+ You should be all set!
38
+
39
+ Usage
40
+ ------
41
+ Check back, because this file will be updated with a lot more usage examples.
42
+
43
+ For simplicity, this gem includes a CLI application for interacting with an API backend. To use it, run:
44
+
45
+ $ antaeus-cli
46
+
47
+ It should be in your `PATH`. On the first run, it will create a directory called `~/.antaeus` (meaning it places it in your home directory), and it will drop a base configuration for the tool at `~/.antaeus/client.yml`. Edit this file, specifically changing `base_url`, `login`, and `password` as required. This document will be updated to show all configuration options available, along with their default values, in the future.
48
+
49
+ The CLI tool really is just a shortcut to the next few lines of boilerplate code to connect to the backend API and reuse configuration from a config file.
50
+
51
+ For a typical custom ruby application, you'll need to do something like the following to get started:
52
+
53
+ require 'antaeus-sdk'
54
+
55
+ # create an 'instance' of the User API Client Singleton
56
+ client = Antaeus::UserAPIClient.instance
57
+ # authenticate
58
+ client.authenticate 'username', 'password'
59
+
60
+ From here, whether using the provided CLI tool or building a custom application, the instructions are the same.
61
+
62
+ First, connect the client to the API backend and obtain an API token:
63
+
64
+ client.connect
65
+
66
+ You'll probably see something similar to the following:
67
+
68
+ => #<RestClient::Resource:0x007fa693ecbbe8
69
+ @block=nil,
70
+ @options=
71
+ {:content_type=>:json,
72
+ :accept=>:json,
73
+ :headers=>{:"X-API-Token:"=>"cv0qTNvJsTRMEn2jzLBvb+T25l6zc8feG3s62Q6XDPbB9isxG3gJ1wxRpyxINHgPRd9lu+afLrIzFj50KjLIFtPkGc5bOJKyO7BCCWFGY0erhbhFpXLJZg=="}},
74
+ @url="https://antaeus.example.com">
75
+
76
+ This API client is built to be very flexible, working for both guest users (using the `GuestAPIClient`), typical users (using the `UserAPIClient` shown in this example), as well as for trusted front-end applications (using the same `UserAPIClient` in multi-user / impersonation mode). For this reason, Antaeus resources (subclasses of the `Antaeus::Resource` class) need to know which client to use to perform a given operation on the backend API. These resources are smart enough to keep using the same client, but a client (a sublcass of the `Antaeus::APIClient` class) must be provided to all class methods. For instance:
77
+
78
+ # Retrieve a list of all Guests known to the system
79
+ guests = Antaeus::Resources::Guest.all(client: client)
80
+
81
+ Note though, that any objects created using a class method with a client provided carry along that same client. This means that method chaining (for instance, on resource collections) is simple:
82
+
83
+ # For simplicity, include the Antaeus::Resources module / namespace
84
+ include Antaeus::Resources
85
+
86
+ # Retrieve all guests with "gmail.com" in their email address
87
+ guests = Guest.all(client: client).where(:email, /gmail\.com/, comparison: :match)
88
+ # Or
89
+ all_guests = Guest.all(client: client)
90
+ guests = all_guests.where(:email, /gmail\.com/, comparison: :match)
91
+ # Or even
92
+ guests = Guest.where(:email, /gmail\.com/, comparison: :match, client: client)
93
+
94
+ The `#where()` is an instance method on the `Antaeus::ResourceCollection` class, which means that the searching is actually done locally. For small installations of Antaeus (or especially powerful client machines), this is likely the fastest way to do searching. That said, `Antaeus::Resource` also provides a `.search()` method that submits queries to the server for processing, returning only matching resources. This style of searching is less flexible, and may be slower for some operations given the lazy-loading of resource model data employed by this SDK.
95
+
96
+ The following resource classes (all under the `Antaeus::Resources` namespace) are available for typical API operations:
97
+
98
+ * `Appointment`
99
+ * Used for creating, listing, and managing guest appointments
100
+ * `Group`
101
+ * Read-only, used for listing and querying backend groups and their members. Only available to administrators and via the `UserAPIClient`
102
+ * `Guest`
103
+ * Used for creating, listing, and managing guests.
104
+ * `Hook`
105
+ * Used to configure plugins, targeting certain plugins at named system events. Only available to administrators and via the `UserAPIClient`
106
+ * `Location`
107
+ * Used for creating, listing, and managing office locations. Read-only to non-administrators.
108
+ * `RemoteApplication`
109
+ * Used for creating, listing, and managing remote front-end applications to the API. This is for very advanced cases only (such as integrating with different authentication systems). Only available to administrators and via the `UserAPIClient`
110
+ * `User`
111
+ * Read-only, used for listing and querying backend users.
112
+
113
+ These do not correlate 1:1 with objects defined in the API, but they are a close and convenient approximation.
114
+
115
+ License
116
+ -------
117
+ This project and all code contained within it are released under the [MIT License](https://opensource.org/licenses/MIT). As stated in [CONTRIBUTING](CONTRIBUTING.md):
118
+
119
+ > All contributions to this project will be released under the [MIT License](https://opensource.org/licenses/MIT). By submitting a pull request, you are agreeing to comply with this license and for any contributions to be released under it.
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pry'
4
+ require 'antaeus-sdk'
5
+
6
+ include Antaeus::Resources
7
+ client = Antaeus::UserAPIClient.instance
8
+
9
+ puts "Starting up..."
10
+
11
+ # Create or load a config file
12
+ apprc_dir = File.expand_path(File.join("~", ".antaeus"))
13
+ config_file = File.expand_path(File.join(apprc_dir, "client.yml"))
14
+
15
+ if File.readable?(config_file)
16
+ CONFIG = YAML.load_file(config_file)
17
+ else
18
+ CONFIG = {
19
+ mode: 'singleuser',
20
+ group_name_attribute: 'cn',
21
+ base_url: 'http://localhost:8080',
22
+ login: 'username',
23
+ password: 'passw0rd',
24
+ debug: false
25
+ }
26
+ puts "Writing base config to `#{config_file}`"
27
+ FileUtils.mkdir_p(File.dirname(config_file))
28
+ File.open(config_file, 'w') {|f| f.write(CONFIG.to_yaml) }
29
+ puts "Please edit this config before running antaeus-cli"
30
+ exit 1
31
+ end
32
+
33
+ Pry.config.prompt = [ proc { "(antaeus)> " }, proc { "(antaeus)*" } ]
34
+
35
+ binding.pry
@@ -0,0 +1,58 @@
1
+ # Standard Library requirements
2
+ require 'fileutils'
3
+ require 'base64'
4
+ require 'yaml'
5
+ require 'json'
6
+ require 'ostruct'
7
+ require 'singleton'
8
+ require 'uri'
9
+ require 'linguistics'
10
+ Linguistics.use(:en)
11
+
12
+ # External Requirements
13
+ require 'crypt/blowfish'
14
+ require 'rest-client'
15
+ require 'will_paginate'
16
+ require 'will_paginate/array'
17
+ require 'addressable/uri'
18
+
19
+ # Internal Requirements
20
+ require 'antaeus-sdk/version'
21
+ require 'antaeus-sdk/helpers/string'
22
+ include Antaeus::Helpers
23
+
24
+ require 'antaeus-sdk/exception'
25
+ require 'antaeus-sdk/exceptions/approval_change_failed'
26
+ require 'antaeus-sdk/exceptions/authentication_failure'
27
+ require 'antaeus-sdk/exceptions/checkin_change_failed'
28
+ require 'antaeus-sdk/exceptions/checkout_change_failed'
29
+ require 'antaeus-sdk/exceptions/immutable_instance'
30
+ require 'antaeus-sdk/exceptions/immutable_modification'
31
+ require 'antaeus-sdk/exceptions/invalid_api_client'
32
+ require 'antaeus-sdk/exceptions/invalid_config_data'
33
+ require 'antaeus-sdk/exceptions/invalid_entity'
34
+ require 'antaeus-sdk/exceptions/invalid_input'
35
+ require 'antaeus-sdk/exceptions/invalid_options'
36
+ require 'antaeus-sdk/exceptions/invalid_property'
37
+ require 'antaeus-sdk/exceptions/invalid_where_query'
38
+ require 'antaeus-sdk/exceptions/login_required'
39
+ require 'antaeus-sdk/exceptions/missing_api_client'
40
+ require 'antaeus-sdk/exceptions/missing_entity'
41
+ require 'antaeus-sdk/exceptions/missing_path'
42
+ require 'antaeus-sdk/exceptions/new_instance_with_id'
43
+ require 'antaeus-sdk/config'
44
+ Antaeus.config.load # Load config before requiring other classes
45
+
46
+ require 'antaeus-sdk/api_client'
47
+ require 'antaeus-sdk/api_info'
48
+ require 'antaeus-sdk/guest_api_client'
49
+ require 'antaeus-sdk/user_api_client'
50
+ require 'antaeus-sdk/resource'
51
+ require 'antaeus-sdk/resource_collection'
52
+ require 'antaeus-sdk/resources/appointment'
53
+ require 'antaeus-sdk/resources/guest'
54
+ require 'antaeus-sdk/resources/group'
55
+ require 'antaeus-sdk/resources/hook'
56
+ require 'antaeus-sdk/resources/location'
57
+ require 'antaeus-sdk/resources/remote_application'
58
+ require 'antaeus-sdk/resources/user'
@@ -0,0 +1,105 @@
1
+ module Antaeus
2
+ # This class is the actual API client, which is a smart wrapper around RestClient
3
+ class APIClient
4
+ def self.instance
5
+ new
6
+ end
7
+
8
+ def initialize
9
+ end
10
+
11
+ # override this method
12
+ def authenticate(login, pass)
13
+ false
14
+ end
15
+
16
+ # override this method
17
+ def authenticated?
18
+ false
19
+ end
20
+
21
+ # override this method
22
+ def connect
23
+ false
24
+ end
25
+
26
+ def connected?
27
+ @rest_client ? true : false
28
+ end
29
+
30
+ def delete(uri)
31
+ client_action do
32
+ raw[Addressable::URI.escape(uri)].delete
33
+ end
34
+ end
35
+
36
+ def get(uri, data = nil)
37
+ client_action do
38
+ if data
39
+ JSON.load raw[Addressable::URI.escape(uri)].get(params: data)
40
+ else
41
+ JSON.load raw[Addressable::URI.escape(uri)].get
42
+ end
43
+ end
44
+ end
45
+
46
+ def post(uri, data)
47
+ client_action do
48
+ JSON.load raw[Addressable::URI.escape(uri)].post(json_escape(data.to_json))
49
+ end
50
+ end
51
+
52
+ def patch(uri, data)
53
+ client_action do
54
+ response = raw[Addressable::URI.escape(uri)].patch(json_escape(data.to_json))
55
+ if response && !response.empty?
56
+ JSON.load(response)
57
+ else
58
+ true
59
+ end
60
+ end
61
+ end
62
+
63
+ def put(uri, data)
64
+ client_action do
65
+ raw[Addressable::URI.escape(uri)].put(json_escape(data.to_json))
66
+ end
67
+ end
68
+
69
+ def raw
70
+ @rest_client
71
+ end
72
+
73
+ # This needs to be caught by whatever is using the SDK to get new user creds
74
+ def refresh_token
75
+ @rest_client = nil
76
+ raise Exceptions::LoginRequired
77
+ end
78
+
79
+ private
80
+
81
+ def json_escape(s)
82
+ json_escape = {
83
+ '&' => '\u0026',
84
+ '>' => '\u003e',
85
+ '<' => '\u003c',
86
+ '%' => '\u0025',
87
+ "\u2028" => '\u2028',
88
+ "\u2029" => '\u2029'
89
+ }
90
+ json_escape_regex = /[\u2028\u2029&><%]/u
91
+
92
+ s.to_s.gsub(json_escape_regex, json_escape)
93
+ end
94
+
95
+ def client_action(&block)
96
+ begin
97
+ yield if connect
98
+ rescue RestClient::Exception => e
99
+ raise e, e.response unless e.http_code == 401 # This rescue only helps with token refreshing
100
+ refresh_token
101
+ yield if connect
102
+ end
103
+ end # client_action()
104
+ end
105
+ end
@@ -0,0 +1,47 @@
1
+ module Antaeus
2
+ module APIInfo
3
+ def self.version(options = {})
4
+ validate_options(options)
5
+
6
+ options[:client].get('/info/version')['api']['version']
7
+ end
8
+
9
+ def self.status(options = {})
10
+ validate_options(options)
11
+
12
+ options[:client].get('/info/status')['api']['status']
13
+ end
14
+
15
+ def self.capabilities(options = {})
16
+ validate_options(options)
17
+
18
+ options[:client].get('/info/capabilities')['api']['capabilities']
19
+ end
20
+
21
+ def self.plugins(options = {})
22
+ validate_options(options)
23
+
24
+ options[:client].get('/info/plugins')['api']['plugins']
25
+ end
26
+
27
+ def self.metrics(options = {})
28
+ validate_options(options)
29
+
30
+ options[:client].get('/info/metrics')['api']['metrics']
31
+ end
32
+
33
+ def self.me(options = {})
34
+ validate_options(options)
35
+
36
+ options[:client].get('/info/me')['current_user']
37
+ end
38
+
39
+ private
40
+
41
+ def self.validate_options(options)
42
+ raise Exceptions::InvalidOptions unless options.is_a?(Hash)
43
+ raise Exceptions::MissingAPIClient unless options[:client]
44
+ raise Exceptions::InvalidAPIClient unless options[:client].is_a?(APIClient)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ # A generic way of constructing a mergeable configuration
2
+ class Antaeus::Config < OpenStruct
3
+ # Construct a base config using the following order of precedence:
4
+ # * environment variables
5
+ # * YAML file
6
+ # * defaults
7
+ def load
8
+ # First, apply the defaults
9
+ defaults = {
10
+ group_name_attribute: :cn,
11
+ user_login_attribute: :uid,
12
+ user_firstname_attribute: :givenName,
13
+ user_lastname_attribute: :sn,
14
+ user_mail_attribute: :mail,
15
+ base_url: 'http://localhost:8080',
16
+ login: 'username',
17
+ password: 'p@assedWard!'
18
+ }
19
+ merge defaults
20
+
21
+ # Then apply the config file, if one exists
22
+ begin
23
+ apprc_dir = File.expand_path(File.join('~', '.antaeus'))
24
+ config_file = File.expand_path(File.join(apprc_dir, 'client.yml'))
25
+ merge YAML.load_file(config_file) if File.readable?(config_file)
26
+ rescue => e
27
+ puts "Unable to read from ~/.antaeus/client.yml"
28
+ end
29
+
30
+ # Finally, apply any environment variables specified
31
+ env_conf = {}
32
+ defaults.keys.each do |key|
33
+ antaeus_key = "ANTAEUS_#{key}".upcase
34
+ env_conf[key] = ENV[antaeus_key] if ENV.key?(antaeus_key)
35
+ end
36
+ merge env_conf unless env_conf.empty?
37
+ end
38
+
39
+ def merge(data)
40
+ raise Exceptions::InvalidConfigData unless data.is_a?(Hash)
41
+ data.each do |k, v|
42
+ self[k.to_sym] = v
43
+ end
44
+ end
45
+ end
46
+
47
+ # Make the config available as a singleton
48
+ module Antaeus
49
+ class << self
50
+ def config
51
+ @config ||= Config.new
52
+ end
53
+ end
54
+ end