koinz 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.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/README +0 -0
- data/Rakefile +2 -0
- data/koinz.gemspec +25 -0
- data/lib/koinz/koinz.rb +49 -0
- data/lib/koinz/notification.rb +41 -0
- data/lib/koinz/omniauth_client.rb +66 -0
- data/lib/koinz/redis.rb +44 -0
- data/lib/koinz/version.rb +3 -0
- data/lib/koinz.rb +4 -0
- metadata +119 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
data/koinz.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "koinz/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "koinz"
|
7
|
+
s.version = Koinz::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Gautam Rege"]
|
10
|
+
s.email = ["gautam@joshsoftware.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{The koinz client library - for oauth & notification management}
|
13
|
+
s.description = %q{Koinz clients require authentication via oauth koinz provider. They can also publish/subscribe for notifications in the koinz environment. }
|
14
|
+
|
15
|
+
s.rubyforge_project = "koinz"
|
16
|
+
|
17
|
+
s.add_dependency('redis')
|
18
|
+
s.add_dependency('omniauth')
|
19
|
+
s.add_dependency('multi_json')
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
data/lib/koinz/koinz.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'omniauth/oauth'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
module OmniAuth
|
5
|
+
module Strategies
|
6
|
+
class Koinz < OAuth2
|
7
|
+
|
8
|
+
def initialize(app, api_key = nil, secret_key = nil, options = {}, &block)
|
9
|
+
client_options = {
|
10
|
+
:site => KOINZ_PROVIDER_URL,
|
11
|
+
:authorize_url => "#{KOINZ_PROVIDER_URL}/auth/koinz/authorize",
|
12
|
+
:access_token_url => "#{KOINZ_PROVIDER_URL}/auth/koinz/access_token"
|
13
|
+
}
|
14
|
+
super(app, :koinz, api_key, secret_key, client_options, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def secure_callback_url
|
18
|
+
SECURE_CALLBACK_HOST + "#{OmniAuth.config.path_prefix}/#{name}/secure_callback"
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def user_data
|
24
|
+
@data ||= MultiJson.decode(@access_token.get("/auth/koinz/user.json"))
|
25
|
+
end
|
26
|
+
|
27
|
+
def request_phase
|
28
|
+
options[:scope] ||= "read"
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def user_hash
|
33
|
+
user_data
|
34
|
+
end
|
35
|
+
|
36
|
+
def auth_hash
|
37
|
+
OmniAuth::Utils.deep_merge(super, {
|
38
|
+
'uid' => user_data["uid"],
|
39
|
+
'user_info' => user_data['user_info'],
|
40
|
+
'extra' => {
|
41
|
+
'admin' => user_data['extra']['admin'],
|
42
|
+
'first_name' => user_data['extra']['first_name'],
|
43
|
+
'last_name' => user_data['extra']['last_name'],
|
44
|
+
}
|
45
|
+
})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Koinz
|
4
|
+
class Notification
|
5
|
+
|
6
|
+
# subscribe - its always pattern subscribe
|
7
|
+
# This is *always* spawned in a different thread. Eact SET of events
|
8
|
+
# is subscribed to in a different thread. You can call this multiple times.
|
9
|
+
# Please remember -- if you subscribe to common patterns. eg. f* and foo,
|
10
|
+
# you will receive the callback twice!!
|
11
|
+
def self.subscribe(*events, &block)
|
12
|
+
Thread.new do
|
13
|
+
# Since we gather the events as an array an not variable arguments,
|
14
|
+
# it is necessary to flatten the event array before passing it to
|
15
|
+
# psubscribe
|
16
|
+
|
17
|
+
# Process pending messages first!
|
18
|
+
REDIS_SUB.pending_messages(events.flatten, &block)
|
19
|
+
|
20
|
+
REDIS_SUB.psubscribe(*(events.flatten)) do |on|
|
21
|
+
on.psubscribe do |event, total|
|
22
|
+
Rails.logger.info("Subscribed to ##{event} (#{total} subscriptions)")
|
23
|
+
end
|
24
|
+
|
25
|
+
on.pmessage do |pattern, event, message|
|
26
|
+
block.call(event, MultiJson.decode(message))
|
27
|
+
end
|
28
|
+
|
29
|
+
on.punsubscribe do |event, total|
|
30
|
+
Rails.logger.info("Unsubscribed for ##{event} (#{total} subscriptions)")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
Rails.logger.info("Exiting Koinz::Notification.subscribe")
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.publish(event, payload)
|
38
|
+
REDIS.publish(event, payload)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'omniauth/oauth'
|
2
|
+
require 'multi_json'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module Koinz
|
6
|
+
module OAuth2Client
|
7
|
+
|
8
|
+
class UserManager
|
9
|
+
# @param [String] the access token
|
10
|
+
# @param [String] uri for invocation on remote host
|
11
|
+
# @param [Hash] options.
|
12
|
+
# :method => :get (default) [ :put, :post, :delete ]
|
13
|
+
# Example:
|
14
|
+
# Koinz::OAuth2::UserManager.call(@user_session.auth_token, '/users/sign_out.json')
|
15
|
+
def self.call(access_token, uri, options = {})
|
16
|
+
access_token = OAuth2::AccessToken.new($KOINZ_PROVIDER.client, access_token )
|
17
|
+
|
18
|
+
method = options.fetch(:method, :get)
|
19
|
+
result = access_token.send(method, uri)
|
20
|
+
result = MultiJson.decode(result)
|
21
|
+
rescue Exception => e
|
22
|
+
return { :error => e.message }
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class Application
|
28
|
+
# @param [String] the access token
|
29
|
+
# @param [String] HOST to be contacted, eg. 'http://merchant.koinz.com'
|
30
|
+
# @param [String] uri for invocation on remote host (ONLY JSON supported)
|
31
|
+
# @param [Hash] params to be passed in the URL
|
32
|
+
# TODO: Do we need to support Http-post?
|
33
|
+
# Example:
|
34
|
+
# Koinz::OAuth2Client.Application.call(@user_session.auth_token, MERCHANT_APP, '/merchant', :name => 'name'
|
35
|
+
def self.call(access_token, host, uri, params = {})
|
36
|
+
# Prepare the entire URL
|
37
|
+
request_uri = "#{host}/#{uri}?access_token=#{access_token}"
|
38
|
+
|
39
|
+
# Add the params
|
40
|
+
params.each_pair do |k,v|
|
41
|
+
request_uri += "&#{k}=#{v}"
|
42
|
+
end
|
43
|
+
|
44
|
+
response = Net::HTTP.get_response(URI.parse(request_uri))
|
45
|
+
result = ActiveSupport::JSON.decode(response.body)
|
46
|
+
return result
|
47
|
+
|
48
|
+
rescue Exception => e
|
49
|
+
return { :error => e.message }
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.secure_token(strategy)
|
53
|
+
client = strategy.client
|
54
|
+
|
55
|
+
req_params = client.web_server.access_token_params(nil, { :redirect_uri => strategy.secure_callback_url})
|
56
|
+
req_params.delete('code')
|
57
|
+
|
58
|
+
response = client.request(:post, client.access_token_url, req_params)
|
59
|
+
params = MultiJson.decode(response) rescue nil
|
60
|
+
params = Rack::Utils.parse_query(response) unless params.is_a? Hash
|
61
|
+
|
62
|
+
OAuth2::AccessToken.new(client, params['access_token'], params['refresh_token'], params['expires_in'])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/koinz/redis.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
class KoinzRedis < Redis
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@timestamp = options[:timestamp].to_i || 0 # 0 mean -- no backlog needed
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def publish(channel, message)
|
12
|
+
timestamp = Time.now.to_i
|
13
|
+
zadd(channel, timestamp, MultiJson.encode([channel, message]))
|
14
|
+
super(channel, MultiJson.encode(message))
|
15
|
+
end
|
16
|
+
|
17
|
+
# returns the pending messages [ event, payload ] pairs
|
18
|
+
# Events are ordered sets based on timstamp!
|
19
|
+
def pending_messages(channels, &block)
|
20
|
+
return if @timestamp == 0
|
21
|
+
|
22
|
+
Rails.logger.info('Processing Pending messages')
|
23
|
+
events = channels.collect {|e| keys(e)}.flatten
|
24
|
+
|
25
|
+
return if not events or events.empty? # no events to process
|
26
|
+
|
27
|
+
destination = "pending-#{Time.now.to_i}"
|
28
|
+
zunionstore(destination, events)
|
29
|
+
# We want events only after the timestamp!
|
30
|
+
messages = zrangebyscore(destination, "(#{@timestamp.to_s}", "+inf")
|
31
|
+
|
32
|
+
# Pending messages are from sorted sets (ordered by timestamp)
|
33
|
+
# No need to send the timestamp for now -- but we store it just in case!
|
34
|
+
messages.each do |message|
|
35
|
+
event, payload = MultiJson.decode(message)
|
36
|
+
block.call(event, payload)
|
37
|
+
end
|
38
|
+
|
39
|
+
# cleanup
|
40
|
+
del(destination)
|
41
|
+
|
42
|
+
Rails.logger.info('Completed processing of pending messages')
|
43
|
+
end
|
44
|
+
end
|
data/lib/koinz.rb
ADDED
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: koinz
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Gautam Rege
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-05 00:00:00 +05:30
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: redis
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: omniauth
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: multi_json
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
description: "Koinz clients require authentication via oauth koinz provider. They can also publish/subscribe for notifications in the koinz environment. "
|
64
|
+
email:
|
65
|
+
- gautam@joshsoftware.com
|
66
|
+
executables: []
|
67
|
+
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- .gitignore
|
74
|
+
- Gemfile
|
75
|
+
- README
|
76
|
+
- Rakefile
|
77
|
+
- koinz.gemspec
|
78
|
+
- lib/koinz.rb
|
79
|
+
- lib/koinz/koinz.rb
|
80
|
+
- lib/koinz/notification.rb
|
81
|
+
- lib/koinz/omniauth_client.rb
|
82
|
+
- lib/koinz/redis.rb
|
83
|
+
- lib/koinz/version.rb
|
84
|
+
has_rdoc: true
|
85
|
+
homepage: ""
|
86
|
+
licenses: []
|
87
|
+
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 3
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
hash: 3
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
version: "0"
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project: koinz
|
114
|
+
rubygems_version: 1.3.7
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: The koinz client library - for oauth & notification management
|
118
|
+
test_files: []
|
119
|
+
|