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,198 @@
1
+ module Antaeus
2
+ # The ResourceCollection class
3
+ # Should not allow or use mixed types
4
+ class ResourceCollection
5
+ include Enumerable
6
+ include Comparable
7
+
8
+ # @return [Class] this is a collection of this {Resource} subclass
9
+ attr_reader :type
10
+
11
+ def initialize(list, options = {})
12
+ raise Exceptions::InvalidOptions unless options.is_a?(Hash)
13
+ raise Exceptions::MissingAPIClient unless options[:client]
14
+ raise Exceptions::InvalidAPIClient unless options[:client].is_a?(APIClient)
15
+ raise Exceptions::InvalidInput if list.empty? and options[:type].nil?
16
+ @client = options[:client]
17
+ @list = list
18
+ if options[:type]
19
+ @type = options[:type]
20
+ else
21
+ @type = list.first.class
22
+ end
23
+ end
24
+
25
+ def each(&block)
26
+ @list.each(&block)
27
+ end
28
+
29
+ # Does the collection contain anything?
30
+ # @return [Boolean]
31
+ def empty?
32
+ @list.empty?
33
+ end
34
+
35
+ def first(n = nil)
36
+ if n
37
+ self.class.new(@list.first(n), type: @type, client: @client)
38
+ else
39
+ @list.first
40
+ end
41
+ end
42
+
43
+ def last(n = nil)
44
+ if n
45
+ self.class.new(@list.last(n), type: @type, client: @client)
46
+ else
47
+ @list.last
48
+ end
49
+ end
50
+
51
+ # Merge two collections
52
+ # @return [ResourceCollection]
53
+ def merge(other)
54
+ if other.is_a?(self.class)
55
+ new_list = @list.dup
56
+ self + (other - self)
57
+ else
58
+ fail Exceptions::InvalidInput
59
+ end
60
+ end
61
+
62
+ # Makes #model compatible with the server-side
63
+ def model
64
+ type
65
+ end
66
+
67
+ # Hacked together #or() method in the same spirit as #where().
68
+ # This method can be chained for multiple / more specific queries.
69
+ #
70
+ # @param attribute [Symbol] the attribute to query
71
+ # @param value [Object] the value to compare against
72
+ # @param comparison_method [String,Symbol] the method to use for comparison
73
+ # - allowed options are "'==', '!=', '>', '>=', '<', '<=', and 'match'"
74
+ # @raise [Exceptions::InvalidWhereQuery] if not the right kind of comparison
75
+ # @return [ResourceCollection]
76
+ def or(attribute, value, options = {})
77
+ options[:comparison] ||= '=='
78
+ if empty?
79
+ @type.where(attribute, value, comparison: options[:comparison], client: @client)
80
+ else
81
+ merge first.class.where(
82
+ attribute, value,
83
+ comparison: options[:comparison],
84
+ client: @client
85
+ )
86
+ end
87
+ end
88
+
89
+ # Pass pagination through to the Array (which passes to will_paginate)
90
+ def paginate(*args)
91
+ @list.paginate(*args)
92
+ end
93
+
94
+ # Returns the number of Resource instances in the collection
95
+ # @return [Fixnum]
96
+ def size
97
+ @list.size
98
+ end
99
+
100
+ # Allow complex sorting like an Array
101
+ # @return [ResourceCollection] sorted collection
102
+ def sort(&block)
103
+ self.class.new(super(&block), type: @type, client: @client)
104
+ end
105
+
106
+ # Horribly inefficient way to allow querying Resources by their attributes.
107
+ # This method can be chained for multiple / more specific queries.
108
+ #
109
+ # @param attribute [Symbol] the attribute to query
110
+ # @param value [Object] the value to compare against
111
+ # @param comparison_method [String,Symbol] the method to use for comparison
112
+ # - allowed options are "'==', '!=', '>', '>=', '<', '<=', and 'match'"
113
+ # @raise [Exceptions::InvalidWhereQuery] if not the right kind of comparison
114
+ # @return [ResourceCollection]
115
+ def where(attribute, value, options = {})
116
+ valid_comparisons = [:'==', :'!=', :>, :'>=', :<, :'<=', :match]
117
+ options[:comparison] ||= '=='
118
+ unless valid_comparisons.include?(options[:comparison].to_sym)
119
+ fail Exceptions::InvalidWhereQuery
120
+ end
121
+ self.class.new(
122
+ @list.collect do |item|
123
+ if item.send(attribute).nil?
124
+ nil
125
+ else
126
+ item if item.send(attribute).send(options[:comparison].to_sym, value)
127
+ end
128
+ end.compact,
129
+ type: @type,
130
+ client: @client
131
+ )
132
+ end
133
+
134
+ alias_method :and, :where
135
+
136
+ # Return the collection item at the specified index
137
+ # @return [Resource,ResourceCollection] the item at the requested index
138
+ def [](index)
139
+ if index.is_a?(Range)
140
+ self.class.new(@list[index], type: @type, client: @client)
141
+ else
142
+ @list[index]
143
+ end
144
+ end
145
+
146
+ # Return a collection after subtracting from the original
147
+ # @return [ResourceCollection]
148
+ def -(other)
149
+ new_list = @list.dup
150
+ if other.respond_to?(:to_a)
151
+ other.to_a.each do |item|
152
+ new_list.delete_if { |res| res.id == item.id }
153
+ end
154
+ elsif other.is_a?(Resource)
155
+ new_list.delete_if { |res| res.id == other.id }
156
+ else
157
+ raise Exceptions::InvalidInput
158
+ end
159
+ self.class.new(new_list, type: @type, client: @client)
160
+ end
161
+
162
+ # Return a collection after adding to the original
163
+ # Warning: this may cause duplicates or mixed type joins! For safety,
164
+ # use #merge
165
+ # @return [ResourceCollection]
166
+ def +(other)
167
+ if other.is_a?(self.class)
168
+ self.class.new(@list + other.to_a, type: @type, client: @client)
169
+ elsif other.is_a?(@type)
170
+ self.class.new(@list + [other], type: @type, client: @client)
171
+ else
172
+ fail Exceptions::InvalidInput
173
+ end
174
+ end
175
+
176
+ def <<(other)
177
+ if other.class == @type
178
+ @list << other
179
+ else
180
+ fail Exceptions::InvalidInput
181
+ end
182
+ end
183
+
184
+ def <=>(other)
185
+ collect(&:id).sort <=> other.collect(&:id).sort
186
+ end
187
+
188
+ # Allow comparison of collection
189
+ # @return [Boolean] do the collections contain the same resource ids?
190
+ def ==(other)
191
+ if other.is_a? self.class
192
+ collect(&:id).sort == other.collect(&:id).sort
193
+ else
194
+ false
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,166 @@
1
+ module Antaeus
2
+ module Resources
3
+ class Appointment < Resource
4
+ property :arrival, type: :time
5
+ property :comment
6
+ property :contact
7
+ property :departure, type: :time
8
+ property :location_id
9
+ property :guest_id
10
+ property :created_at, read_only: true, type: :time
11
+ property :created_by, read_only: true
12
+ property :arrived?, read_only: true
13
+ property :approved?, read_only: true
14
+ property :departed?, read_only: true
15
+ property :checkin_time, read_only: true, type: :time
16
+ property :checkout_time, read_only: true, type: :time
17
+
18
+ path :all, '/appointments'
19
+
20
+ # A collection of all upcoming appointments
21
+ def self.upcoming(options = {})
22
+ validate_options(options)
23
+ ResourceCollection.new(
24
+ options[:client].get("#{path_for(:all)}/upcoming")['appointments'].collect do |record|
25
+ self.new(
26
+ entity: record,
27
+ lazy: true,
28
+ tainted: false,
29
+ client: options[:client]
30
+ )
31
+ end,
32
+ type: self,
33
+ client: options[:client]
34
+ )
35
+ end
36
+
37
+ # Generate a report of appointments based on some criteria
38
+ def self.report(options = {})
39
+ validate_options(options)
40
+ ResourceCollection.new(
41
+ options[:client].post("/reports/generate", q: options[:criteria])['appointments'].collect do |record|
42
+ self.new(
43
+ entity: record,
44
+ lazy: false,
45
+ tainted: false,
46
+ client: options[:client]
47
+ )
48
+ end,
49
+ type: self,
50
+ client: options[:client]
51
+ )
52
+ end
53
+
54
+ # Approve an Appointment
55
+ def approve
56
+ if @client.patch("#{path_for(:all)}/#{id}/approve", approve: true)
57
+ true
58
+ else
59
+ fail Exceptions::ApprovalChangeFailed
60
+ end
61
+ reload
62
+ return true
63
+ end
64
+
65
+ # Checkin a Guest
66
+ def checkin
67
+ if @client.patch("#{path_for(:all)}/#{id}/checkin", email: guest.email)
68
+ true
69
+ else
70
+ raise Exceptions::CheckinChangeFailed
71
+ end
72
+ reload
73
+ return true
74
+ end
75
+
76
+ # Checkout a Guest
77
+ def checkout
78
+ if @client.patch("#{path_for(:all)}/#{id}/checkout", email: guest.email)
79
+ true
80
+ else
81
+ raise Exceptions::CheckoutChangeFailed
82
+ end
83
+ reload
84
+ return true
85
+ end
86
+
87
+ # Hidden property used to lookup related resource
88
+ def guest
89
+ Guest.get(@entity['guest_id'], client: @client)
90
+ end
91
+
92
+ # Set the guest associated with this appointment
93
+ def guest=(guest_or_guest_id)
94
+ @entity['guest_id'] = if guest_or_guest_id.is_a?(Guest)
95
+ guest_or_guest_id.id
96
+ else
97
+ guest_or_guest_id
98
+ end
99
+ @tainted = true
100
+ end
101
+
102
+ # Hidden property used to lookup related resource
103
+ def location
104
+ Location.get(@entity['location_id'], client: @client)
105
+ end
106
+
107
+ # Set the location associated with this appointment
108
+ def location=(location_or_location_id)
109
+ @entity['location_id'] = if location_or_location_id.is_a?(Location)
110
+ location_or_location_id.id
111
+ else
112
+ location_or_location_id
113
+ end
114
+ @tainted = true
115
+ end
116
+
117
+ # Unapprove an Appointment
118
+ def unapprove
119
+ if @client.patch("#{path_for(:all)}/#{id}/approve", approve: false)
120
+ true
121
+ else
122
+ fail Exceptions::ApprovalChangeFailed
123
+ end
124
+ reload
125
+ return true
126
+ end
127
+
128
+ # Checkin a Guest
129
+ def undo_checkin
130
+ if @client.delete("#{path_for(:all)}/#{id}/checkin")
131
+ true
132
+ else
133
+ raise Exceptions::CheckinChangeFailed
134
+ end
135
+ reload
136
+ return true
137
+ end
138
+
139
+ # Checkout a Guest
140
+ def undo_checkout
141
+ if @client.delete("#{path_for(:all)}/#{id}/checkout")
142
+ true
143
+ else
144
+ raise Exceptions::CheckoutChangeFailed
145
+ end
146
+ reload
147
+ return true
148
+ end
149
+
150
+ # User related to an appointment
151
+ def user
152
+ User.get(contact, client: @client)
153
+ end
154
+
155
+ # Set the user related to an appointment
156
+ def user=(username)
157
+ contact = if username.is_a?(User)
158
+ username.id
159
+ else
160
+ username
161
+ end
162
+ @tainted = true
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,27 @@
1
+ module Antaeus
2
+ module Resources
3
+ class Group < Resource
4
+ delayed_property { Antaeus.config.group_name_attribute || :cn }
5
+
6
+ path :all, '/groups'
7
+ immutable true
8
+
9
+ def members
10
+ ResourceCollection.new(
11
+ @client.get("#{path_for(:all)}/#{id}/members")['users'].collect do |record|
12
+ User.new(
13
+ entity: record,
14
+ lazy: true,
15
+ tainted: false,
16
+ client: @client
17
+ )
18
+ end,
19
+ type: Antaeus::Resources::User,
20
+ client: @client
21
+ )
22
+ end
23
+
24
+ alias_method :users, :members
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ module Antaeus
2
+ module Resources
3
+ class Guest < Resource
4
+ property :email
5
+ property :full_name
6
+ property :phone
7
+ property :citizenship
8
+ property :need_nda
9
+ property :signed_nda
10
+ property :need_tcpa
11
+ property :signed_tcpa
12
+ property :pin
13
+ property :created_at, read_only: true, type: :time
14
+
15
+ path :all, '/guests'
16
+
17
+ def appointments
18
+ ResourceCollection.new(
19
+ @client.get("#{path_for(:all)}/#{id}/appointments")['appointments'].collect do |record|
20
+ Appointment.new(
21
+ entity: record,
22
+ lazy: true,
23
+ tainted: false,
24
+ client: @client
25
+ )
26
+ end,
27
+ type: Antaeus::Resources::Appointment,
28
+ client: @client
29
+ )
30
+ end
31
+
32
+ def available_appointments(location)
33
+ upcoming_appointments.where(location: location)
34
+ end
35
+
36
+ def upcoming_appointments
37
+ Appointment.upcoming(client: client).where(:guest_id, id)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ module Antaeus
2
+ module Resources
3
+ class Hook < Resource
4
+ property :name
5
+ property :plugins
6
+ property :configurations
7
+ property :created_at, read_only: true, type: :time
8
+
9
+ path :all, '/hooks'
10
+
11
+ def self.all_available(options = {})
12
+ validate_options(options)
13
+ options[:client].get("#{path_for(:all)}/available")['available_hooks']
14
+ end
15
+ end
16
+ end
17
+ end