hiptail 0.0.1

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,85 @@
1
+ require 'hiptail/authority/provider'
2
+ require 'sqlite3'
3
+
4
+ class HipTail::SQLite3AuthorityProvider < HipTail::AuthorityProvider
5
+ # @return [HipTail::SQLite3AuthorityProvider]
6
+ def initialize(db)
7
+ @authorities = {}
8
+ @db = db
9
+
10
+ build
11
+ end
12
+
13
+ # @return [void]
14
+ def build
15
+ @db.execute_batch <<-'END_SQL'
16
+ CREATE TABLE IF NOT EXISTS hiptail_authority (
17
+ oauth_id VARCHAR(255) NOT NULL PRIMARY KEY,
18
+ oauth_secret VARCHAR(255) NOT NULL,
19
+ authorization_url VARCHAR(255) NOT NULL,
20
+ token_url VARCHAR(255) NOT NULL,
21
+ room_id INT UNSIGNED,
22
+ group_id INT UNSIGNED NOT NULL,
23
+ api_base VARCHAR(255) NOT NULL,
24
+ created_at INTEGER NOT NULL
25
+ );
26
+ END_SQL
27
+ end
28
+
29
+ SQL_GET = <<-'END_SQL'
30
+ SELECT * FROM hiptail_authority WHERE oauth_id = ? LIMIT 1
31
+ END_SQL
32
+
33
+ # @abstract
34
+ # @param [String] oauth_id
35
+ # @return [HipTail::Authority]
36
+ def get(oauth_id)
37
+ unless @authorities.include?(oauth_id)
38
+ begin
39
+ last_rah = @db.results_as_hash
40
+ @db.results_as_hash = true
41
+ @db.execute(SQL_GET, oauth_id) do |row|
42
+ data = row.to_a.select { |f| f[0].is_a?(String) }.map { |f| [ f[0].to_sym, f[1] ] }
43
+ @authorities[oauth_id] = HipTail::Authority.new(Hash[*data.flatten(1)])
44
+ break
45
+ end
46
+ ensure
47
+ @db.results_as_hash = last_rah
48
+ end
49
+ end
50
+
51
+ @authorities[oauth_id]
52
+ end
53
+
54
+ SQL_REGISTER = <<-'END_SQL'
55
+ REPLACE INTO hiptail_authority
56
+ ( oauth_id, oauth_secret, authorization_url, token_url, room_id, group_id, api_base, created_at )
57
+ VALUES ( :oauth_id, :oauth_secret, :authorization_url, :token_url, :room_id, :group_id, :api_base, :created_at )
58
+ END_SQL
59
+
60
+ # @param [String] oauth_id
61
+ # @param [HipTail::Authority] authority
62
+ # @return [HipTail::Authority]
63
+ def register(oauth_id, authority)
64
+ @authorities[oauth_id] = authority
65
+
66
+ row_data = authority.as_hash
67
+ [ :api_base, :authorization_url, :token_url ].each do |key|
68
+ row_data[key] = row_data[key].to_s
69
+ end
70
+ row_data[:created_at] = Time.now.to_i
71
+ @db.execute(SQL_REGISTER, row_data)
72
+ end
73
+
74
+ SQL_UNREGISTER = <<-'END_SQL'
75
+ DELETE FROM hiptail_authority WHERE oauth_id = ?
76
+ END_SQL
77
+
78
+ # @param [String] oauth_id
79
+ # @return [void]
80
+ def unregister(oauth_id)
81
+ @authorities.delete(oauth_id)
82
+
83
+ @db.execute(SQL_UNREGISTER, oauth_id)
84
+ end
85
+ end
@@ -0,0 +1,258 @@
1
+ require 'json'
2
+ require 'uri'
3
+ require 'open-uri'
4
+ require 'net/http'
5
+ require 'oauth2'
6
+
7
+ module HipTail
8
+ class Authority
9
+ # @return [String] Returns OAuth ID.
10
+ attr_reader :oauth_id
11
+ # Returns room_id for room authority.
12
+ # Nil for global authority.
13
+ # @return [String]
14
+ # @return [nil]
15
+ attr_reader :room_id
16
+ # Returns group_id for authority.
17
+ # @return [String]
18
+ attr_reader :group_id
19
+
20
+ # @return [Boolean] Represents whether the authority is for global or not.
21
+ def for_global?
22
+ ! @room_id
23
+ end
24
+ alias global? for_global?
25
+
26
+ # @return [Boolean] Represents whether the authority is for a room or not.
27
+ def for_room?
28
+ ! for_global?
29
+ end
30
+ alias room? for_room?
31
+
32
+ # A new instance of HipTail::Authority.
33
+ # @param [Hash] params
34
+ # @option params [String] :oauth_id
35
+ # @option params [String] :oauth_secret
36
+ # @option params [String] :authorization_url
37
+ # @option params [String] :token_url
38
+ # @option params [String] :room_id
39
+ # @option params [String] :group_id
40
+ # @option params [String] :api_base
41
+ # @return [HipTail::Authority]
42
+ def initialize(params)
43
+ @oauth_id = params[:oauth_id]
44
+ @oauth_secret = params[:oauth_secret]
45
+ @authorization_url = params[:authorization_url]
46
+ @token_url = params[:token_url]
47
+
48
+ @room_id = params[:room_id]
49
+ @group_id = params[:group_id]
50
+
51
+ @room_id = @room_id.to_i if ! @room_id.nil?
52
+ @group_id = @group_id.to_i if ! @group_id.nil?
53
+
54
+ api_base_uri = params[:api_base].to_s
55
+ unless api_base_uri.end_with?('/')
56
+ api_base_uri += '/';
57
+ end
58
+ @api_base = URI.parse(api_base_uri)
59
+ end
60
+
61
+ # @return [Hash] Hash representation. Convenient for persistency.
62
+ def as_hash
63
+ {
64
+ :oauth_id => @oauth_id,
65
+ :oauth_secret => @oauth_secret,
66
+ :authorization_url => @authorization_url,
67
+ :token_url => @token_url,
68
+ :room_id => @room_id,
69
+ :group_id => @group_id,
70
+ :api_base => @api_base,
71
+ }
72
+ end
73
+
74
+ # Issues send notification API.
75
+ # @param [Hash] params Parameters for notification API with :room_id.
76
+ # @option params [String] :room_id Room ID. Optional but mandatory for global authority.
77
+ # @return [Hash] Resulting response of API.
78
+ def send_notification(params)
79
+ room_id = self.room_id || params.delete(:room_id)
80
+ raise ArgumentError.new("room_id required") unless room_id
81
+ call_api(:method => :post, :uri => @api_base.merge("room/#{room_id}/notification"), :body_params => params)
82
+ end
83
+
84
+ # Issues reply message API.
85
+ # @param [Hash] params Parameters for reply message API with :room_id.
86
+ # @option params [String] :room_id Room ID. Optional but mandatory for global authority.
87
+ # @return [Hash] Resulting response of API.
88
+ def reply_message(params)
89
+ room_id = self.room_id || params.delete(:room_id)
90
+ raise ArgumentError.new("room_id required") unless room_id
91
+ call_api(:method => :post, :uri => @api_base.merge("room/#{room_id}/reply"), :body_params => params)
92
+ end
93
+
94
+ # Issues get all rooms API.
95
+ # @param [Hash] params Parameters for get all rooms API.
96
+ # @return [HipTail::Rooms]
97
+ def get_all_rooms(params = {})
98
+ res = call_api(:method => :get, :uri => @api_base.merge("room"), :query_params => params)
99
+ Rooms.new(res)
100
+ end
101
+
102
+ # Issues get room API.
103
+ # @param [Hash] params Parameters for get all room API.
104
+ # @option params [String] :room_id Room ID. Optional but mandatory for global authority.
105
+ # @return [HipTail::Room::Detail]
106
+ def get_room(params)
107
+ room_id = self.room_id || params.delete(:room_id)
108
+ raise ArgumentError.new("room_id required") unless room_id
109
+ res = call_api(:method => :get, :uri => @api_base.merge("room/#{room_id}"), :query_params => params)
110
+ Room::Detail.new(res)
111
+ end
112
+
113
+ # Issues get all members API.
114
+ # @param [Hash] params Parameters for get all members API.
115
+ # @return [HipTail::Users]
116
+ def get_all_members(params)
117
+ room_id = self.room_id || params.delete(:room_id)
118
+ raise ArgumentError.new("room_id required") unless room_id
119
+ res = call_api(:method => :get, :uri => @api_base.merge("room/#{room_id}/member"), :query_params => params)
120
+ Users.new(res)
121
+ end
122
+
123
+ # Issues get all participants API.
124
+ # @param [Hash] params Parameters for get all participants API.
125
+ # @return [HipTail::Users]
126
+ def get_all_participants(params)
127
+ room_id = self.room_id || params.delete(:room_id)
128
+ raise ArgumentError.new("room_id required") unless room_id
129
+ res = call_api(:method => :get, :uri => @api_base.merge("room/#{room_id}/participant"), :query_params => params)
130
+ Users.new(res)
131
+ end
132
+
133
+ # Issues add member API.
134
+ # @param [Hash] params Parameters for add member API with :room_id.
135
+ # @option params [String] :room_id Room ID. Optional but mandatory for global authority.
136
+ # @option params [String] :user_id One of :user_id, :user_mention, :user_email is required.
137
+ # @option params [String] :user_mention
138
+ # @option params [String] :user_email
139
+ # @return [Hash] Resulting response of API.
140
+ def add_member(params)
141
+ room_id = self.room_id || params.delete(:room_id)
142
+ raise ArgumentError.new("room_id required") unless room_id
143
+
144
+ user_name = user_name_from_params(params)
145
+ raise ArgumentError.new("user_id or user_mention or user_email required") unless user_name
146
+
147
+ call_api(:method => :put, :uri => @api_base.merge("room/#{room_id}/member/#{user_name}"), :body_params => params)
148
+ end
149
+
150
+ # Issues remove member API.
151
+ # @param [Hash] params Parameters for remove member API with :room_id.
152
+ # @option params [String] :room_id Room ID. Optional but mandatory for global authority.
153
+ # @option params [String] :user_id One of :user_id, :user_mention, :user_email is required.
154
+ # @option params [String] :user_mention
155
+ # @option params [String] :user_email
156
+ # @return [Hash] Resulting response of API.
157
+ def remove_member(params)
158
+ room_id = self.room_id || params.delete(:room_id)
159
+ raise ArgumentError.new("room_id required") unless room_id
160
+
161
+ user_name = user_name_from_params(params)
162
+ raise ArgumentError.new("user_id or user_mention or user_email required") unless user_name
163
+
164
+ call_api(:method => :delete, :uri => @api_base.merge("room/#{room_id}/member/#{user_name}"), :body_params => params)
165
+ end
166
+
167
+ private
168
+
169
+ def user_name_from_params(params)
170
+ user_id = params.delete(:user_id)
171
+ user_mention = params.delete(:user_mention)
172
+ user_email = params.delete(:user_email)
173
+
174
+ return user_id if user_id
175
+ return "@" + user_mention if user_mention
176
+ return user_email if user_email
177
+ return
178
+ end
179
+
180
+ def call_api(args)
181
+ uri = URI.parse(args[:uri].to_s)
182
+ queries = URI.decode_www_form(uri.query || '').map { |pair| [ pair[0].to_sym, pair[1] ] }
183
+ # XXX Array or Hash, which is better?
184
+ query = Hash[*queries.flatten(1)].merge(args[:query_params] || {})
185
+ query[:auth_token] = token
186
+ uri.query = query.size > 0 ? URI.encode_www_form(query) : nil
187
+
188
+ headers = {
189
+ 'Content-Type' => 'application/json; charset=UTF-8',
190
+ }
191
+
192
+ if args[:body_params]
193
+ body = JSON.generate(args[:body_params] || {})
194
+ headers['Content-Length'] = body.bytesize.to_s
195
+ else
196
+ body = nil
197
+ end
198
+
199
+ case args[:method].to_s.downcase
200
+ when 'get'
201
+ req = Net::HTTP::Get.new(uri.request_uri, headers)
202
+ when 'post'
203
+ req = Net::HTTP::Post.new(uri.request_uri, headers)
204
+ when 'put'
205
+ req = Net::HTTP::Put.new(uri.request_uri, headers)
206
+ when 'delete'
207
+ req = Net::HTTP::Delete.new(uri.request_uri, headers)
208
+ else
209
+ raise
210
+ end
211
+
212
+ req.body = body if body
213
+
214
+ res = http.start do |http|
215
+ http.request(req)
216
+ end
217
+
218
+ if res.content_type =~ %r{\A application/json}x
219
+ return JSON.parse(res.body)
220
+ else
221
+ return {}
222
+ end
223
+ end
224
+
225
+ def token
226
+ if !@token || @token.expired?
227
+ @token = oauth2_client.client_credentials.get_token( :scope => "send_notification send_message admin_room view_group" )
228
+ end
229
+
230
+ @token.token
231
+ end
232
+
233
+ def oauth2_client
234
+ unless @client
235
+ @client = OAuth2::Client.new(
236
+ @oauth_id, @oauth_secret,
237
+ :authorize_url => @authorization_url,
238
+ :token_url => @token_url,
239
+ )
240
+ end
241
+
242
+ @client
243
+ end
244
+
245
+ def http
246
+ unless @http
247
+ @http = Net::HTTP.new(@api_base.host, @api_base.port)
248
+ @http.use_ssl = true if @api_base.scheme == 'https'
249
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
250
+ if ENV["DEBUG_HTTP"]
251
+ @http.set_debug_output($stderr)
252
+ end
253
+ end
254
+
255
+ @http.clone
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,108 @@
1
+ require 'hiptail/atom'
2
+
3
+ module HipTail
4
+ class Event
5
+ attr_accessor :authority
6
+ attr_reader :raw
7
+
8
+ # @return [HipTail::Event]
9
+ def initialize(params)
10
+ @raw = params.dup
11
+ end
12
+
13
+ # @attribute [r] type
14
+ # @return [String]
15
+ def type
16
+ @raw['event']
17
+ end
18
+
19
+ # @attribute [r] oauth_client_id
20
+ # @return [String]
21
+ def oauth_client_id
22
+ @raw['oauth_client_id']
23
+ end
24
+
25
+ # @attribute [r] webhook_id
26
+ # @return [String]
27
+ def webhook_id
28
+ @raw['webhook_id']
29
+ end
30
+
31
+ class << self
32
+ # @param [Hash] params
33
+ # @return [HipTail::Event]
34
+ def parse(params)
35
+ type = params['event']
36
+
37
+ case params['event']
38
+ when 'room_message'
39
+ return Event::RoomMessage.new(params)
40
+ when 'room_notification'
41
+ return Event::RoomNotification.new(params)
42
+ when 'room_enter'
43
+ return Event::RoomEnter.new(params)
44
+ when 'room_exit'
45
+ return Event::RoomExit.new(params)
46
+ else
47
+ return Event.new(params)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ class Event::RoomMessaging < Event
54
+ # @abstract
55
+ # @attribute [r] message
56
+ # @return [HipTail::Messsage]
57
+ def message
58
+ raise
59
+ end
60
+
61
+ # @attribute [r] room
62
+ # @return [HipTail::Room]
63
+ def room
64
+ @room ||= Room.new(@raw['item']['room'])
65
+ @room
66
+ end
67
+ end
68
+
69
+ class Event::RoomMessage < Event::RoomMessaging
70
+ # @attribute [r] message
71
+ # @return [HipTail::Messsage::Talk]
72
+ def message
73
+ @message ||= Message::Talk.new(@raw['item']['message'])
74
+ @message
75
+ end
76
+ end
77
+
78
+ class Event::RoomNotification < Event::RoomMessaging
79
+ # @attribute [r] message
80
+ # @return [HipTail::Messsage::Notification]
81
+ def message
82
+ @message ||= Message::Notification.new(@raw['item']['message'])
83
+ @message
84
+ end
85
+ end
86
+
87
+ class Event::RoomVisiting < Event
88
+ # @attribute [r] sender
89
+ # @return [HipTail::User]
90
+ def sender
91
+ @sender ||= User.create(@raw['item']['sender'])
92
+ @sender
93
+ end
94
+
95
+ # @attribute [r] room
96
+ # @return [HipTail::Room]
97
+ def room
98
+ @room ||= Room.new(@raw['item']['room'])
99
+ @room
100
+ end
101
+ end
102
+
103
+ class Event::RoomEnter < Event::RoomVisiting
104
+ end
105
+
106
+ class Event::RoomExit < Event::RoomVisiting
107
+ end
108
+ end
@@ -0,0 +1,234 @@
1
+ require 'json'
2
+ require 'uri'
3
+ require 'open-uri'
4
+
5
+ require 'hiptail/event'
6
+ require 'hiptail/authority'
7
+ require 'hiptail/authority/provider'
8
+
9
+ module HipTail
10
+ class Manager
11
+ # A new instance of HipTail::Manager.
12
+ # @param [Hash] params ({})
13
+ # @option params [HipTail::AuthorityProvider] :authority_provider (new instance of HipTail::MemoryAuthorityProvider)
14
+ # @return [HipTail::Manager]
15
+ def initialize(params = {})
16
+ @authority_provider = params[:authority_provider] || MemoryAuthorityProvider.new
17
+
18
+ @authority_manager = AuthorityManager.new(@authority_provider)
19
+
20
+ @hook = {}
21
+ [
22
+ :install, :uninstall,
23
+ :event,
24
+ :room_messaging, :room_message, :room_notification,
25
+ :room_visiting, :room_enter, :room_exit,
26
+ ].each do |hook_type|
27
+ @hook[hook_type] = {}
28
+ end
29
+ end
30
+
31
+ # @return [HipTail::AuthorityProvider]
32
+ attr_reader :authority_provider
33
+
34
+ # @param [HipTail::AuthorityProvider] provider
35
+ # @return [HipTail::AuthorityProvider]
36
+ def authority_provider=(provider)
37
+ @authority_provider = @authority_manager.authority_provider = provider
38
+ end
39
+
40
+ # Retrieves authority from oauth_id
41
+ # @attribute [r] authority
42
+ # @example
43
+ # authority = manager.authority[oauth_id]
44
+ # @return [HipTail::Manager::AuthorityManager]
45
+ def authority
46
+ @authority_manager
47
+ end
48
+
49
+ # Registers hook on installation.
50
+ # @return [String] Hook ID
51
+ # @yield [authority]
52
+ # @yield [HipTail::Authority] authority
53
+ def on_install(&block)
54
+ register_hook :install, block
55
+ end
56
+
57
+ # Registers hook on uninstallation.
58
+ # @return [String] Hook ID
59
+ # @yield [oauth_id]
60
+ # @yield [String] oauth_id
61
+ def on_uninstall(&block)
62
+ register_hook :uninstall, block
63
+ end
64
+
65
+ # Registers hook on events.
66
+ # @return [String] Hook ID
67
+ # @yield [event]
68
+ # @yield [HipTail::Event] event
69
+ def on_event(&block)
70
+ register_hook :event, block
71
+ end
72
+
73
+ # Registers hook on messaging events (room_message and room_notification).
74
+ # @return [String] Hook ID
75
+ # @yield [event]
76
+ # @yield [HipTail::Event::RoomMessaging] event
77
+ def on_room_messaging(&block)
78
+ register_hook :room_messaging, block
79
+ end
80
+
81
+ # Registers hook on room_message event.
82
+ # @return [String] Hook ID
83
+ # @yield [event]
84
+ # @yield [HipTail::Event::RoomMessage] event
85
+ def on_room_message(&block)
86
+ register_hook :room_message, block
87
+ end
88
+
89
+ # Registers hook on room_notification event.
90
+ # @return [String] Hook ID
91
+ # @yield [event]
92
+ # @yield [HipTail::Event::RoomNotification] event
93
+ def on_room_notification(&block)
94
+ register_hook :room_notification, block
95
+ end
96
+
97
+ # Registers hook on room visiting event (room_enter and room_exit).
98
+ # @return [String] Hook ID
99
+ # @yield [event]
100
+ # @yield [HipTail::Event::RoomVisiting] event
101
+ def on_room_visiting(&block)
102
+ register_hook :room_visiting, block
103
+ end
104
+
105
+ # Registers hook on room_enter event.
106
+ # @return [String] Hook ID
107
+ # @yield [event]
108
+ # @yield [HipTail::Event::RoomEnter] event
109
+ def on_room_enter(&block)
110
+ register_hook :room_enter, block
111
+ end
112
+
113
+ # Registers hook on room_exit event.
114
+ # @return [String] Hook ID
115
+ # @yield [event]
116
+ # @yield [HipTail::Event::RoomExit] event
117
+ def on_room_exit(&block)
118
+ register_hook :room_exit, block
119
+ end
120
+
121
+ # Handles installing request.
122
+ # @param [Hash] params Request object (originally represented in JSON) from HipChat Server on installation.
123
+ # @return [void]
124
+ def handle_install(params)
125
+ authority = build_authority(params)
126
+
127
+ @authority_provider.register(authority.oauth_id, authority)
128
+
129
+ call_hooks :install, authority
130
+ end
131
+
132
+ # Handles uninstalling request.
133
+ # @note Uninstall event will be fired after uninstallation on the server.
134
+ # So you cannot use oauth information to do something (e.g. sending notification) on uninstallation phase.
135
+ # @param [String] oauth_id Corresponding OAuth ID
136
+ # @return [void]
137
+ def handle_uninstall(oauth_id)
138
+ call_hooks :uninstall, oauth_id
139
+
140
+ @authority_provider.unregister(oauth_id)
141
+ end
142
+
143
+ # Handles events (room_message, room_enter, etc.).
144
+ # @param [Hash] params Request object (originally represented in JSON) from HipChat Server on installation.
145
+ # @return [void]
146
+ def handle_event(params)
147
+ event = Event.parse(params)
148
+ event.authority = self.authority[event.oauth_client_id]
149
+
150
+ call_hooks :event, event
151
+
152
+ if event.is_a?(Event::RoomMessaging)
153
+ call_hooks :room_messaging, event
154
+
155
+ case event
156
+ when Event::RoomMessage
157
+ call_hooks :room_message, event
158
+ when Event::RoomNotification
159
+ call_hooks :room_notification, event
160
+ end
161
+ elsif event.is_a?(Event::RoomVisiting)
162
+ call_hooks :room_visiting, event
163
+
164
+ case event
165
+ when Event::RoomEnter
166
+ call_hooks :room_enter, event
167
+ when Event::RoomExit
168
+ call_hooks :room_exit, event
169
+ end
170
+ end
171
+ end
172
+
173
+ # Registers a hook.
174
+ # @param [Symbol] hook_type
175
+ # @param [Proc] block
176
+ # @param [String] hook_id
177
+ # @return [String] Hook ID
178
+ def register_hook(hook_type, block, hook_id = nil)
179
+ hook_id ||= block.object_id.to_s
180
+ @hook[hook_type][hook_id] = block
181
+ return hook_id
182
+ end
183
+
184
+ # Unregisters a hook.
185
+ # @param [Symbol] hook_type
186
+ # @param [String] hook_id
187
+ # @return [Proc] Unregistered procedure
188
+ def unregister_hook(hook_type, hook_id = nil)
189
+ @hook[hook_type].delete(hook_id.to_s)
190
+ end
191
+
192
+ private
193
+
194
+ def call_hooks(hook_type, *args)
195
+ @hook[hook_type].values.each do |block|
196
+ block.call(*args)
197
+ end
198
+ end
199
+
200
+ def build_authority(params)
201
+ server_cap = JSON.parse(URI.parse(params['capabilitiesUrl']).read)
202
+ oauth2_info = server_cap['capabilities']['oauth2Provider']
203
+ api_base = server_cap['links']['api']
204
+
205
+ HipTail::Authority.new(
206
+ :oauth_id => params['oauthId'],
207
+ :oauth_secret => params['oauthSecret'],
208
+ :room_id => params['roomId'],
209
+ :group_id => params['groupId'],
210
+ :authorization_url => oauth2_info['authorizationUrl'],
211
+ :token_url => oauth2_info['tokenUrl'],
212
+ :api_base => server_cap['links']['api'],
213
+ )
214
+ end
215
+
216
+ # @private
217
+ class AuthorityManager
218
+ # @return [HipTail::AuthorityProvider]
219
+ attr_accessor :authority_provider
220
+
221
+ # @param [HipTail::AuthorityProvider] authority_provider
222
+ # @return [HipTail::Manager::AuthorityManager]
223
+ def initialize(authority_provider)
224
+ @authority_provider = authority_provider
225
+ end
226
+
227
+ # @param [String] oauth_id
228
+ # @return [HipTail::Authority]
229
+ def [](oauth_id)
230
+ @authority_provider.get(oauth_id)
231
+ end
232
+ end
233
+ end
234
+ end