rhosync 2.0.3 → 2.0.4
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/CHANGELOG +5 -0
- data/Rakefile +2 -3
- data/doc/protocol.html +75 -75
- data/lib/rhosync/api/create_client.rb +1 -1
- data/lib/rhosync/api/create_user.rb +1 -1
- data/lib/rhosync/api/delete_client.rb +1 -1
- data/lib/rhosync/api/delete_user.rb +1 -1
- data/lib/rhosync/api/get_api_token.rb +1 -1
- data/lib/rhosync/api/get_client_params.rb +1 -1
- data/lib/rhosync/api/get_db_doc.rb +2 -2
- data/lib/rhosync/api/get_license_info.rb +1 -1
- data/lib/rhosync/api/get_source_params.rb +1 -1
- data/lib/rhosync/api/list_client_docs.rb +1 -1
- data/lib/rhosync/api/list_clients.rb +1 -1
- data/lib/rhosync/api/list_source_docs.rb +1 -1
- data/lib/rhosync/api/list_sources.rb +1 -1
- data/lib/rhosync/api/list_users.rb +1 -1
- data/lib/rhosync/api/ping.rb +2 -2
- data/lib/rhosync/api/push_deletes.rb +1 -1
- data/lib/rhosync/api/push_objects.rb +1 -1
- data/lib/rhosync/api/reset.rb +1 -1
- data/lib/rhosync/api/set_db_doc.rb +1 -1
- data/lib/rhosync/api/set_refresh_time.rb +1 -1
- data/lib/rhosync/api/update_user.rb +1 -1
- data/lib/rhosync/api/upload_file.rb +1 -1
- data/lib/rhosync/console/app/routes/auth.rb +1 -1
- data/lib/rhosync/console/rhosync_api.rb +139 -44
- data/lib/rhosync/model.rb +6 -1
- data/lib/rhosync/store.rb +19 -17
- data/lib/rhosync/version.rb +1 -1
- data/lib/rhosync.rb +2 -1
- data/spec/api/api_helper.rb +2 -2
- data/spec/api/rhosync_api_spec.rb +306 -0
- data/spec/doc/doc_spec.rb +2 -2
- data/spec/model_spec.rb +4 -0
- data/spec/server/server_spec.rb +9 -9
- data/spec/store_spec.rb +26 -18
- metadata +13 -11
@@ -1,7 +1,7 @@
|
|
1
|
-
|
1
|
+
Server.api :get_db_doc do |params,user|
|
2
2
|
if params[:data_type] and params[:data_type] == 'string'
|
3
3
|
Store.get_value(params[:doc])
|
4
4
|
else
|
5
|
-
Store.get_data(params[
|
5
|
+
Store.get_data(params[:doc]).to_json
|
6
6
|
end
|
7
7
|
end
|
data/lib/rhosync/api/ping.rb
CHANGED
data/lib/rhosync/api/reset.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
Server.api :set_refresh_time do |params,user|
|
2
2
|
source = Source.load(params[:source_name],
|
3
3
|
{:app_id => APP_NAME, :user_id => params[:user_name]})
|
4
4
|
source.poll_interval = params[:poll_interval] if params[:poll_interval]
|
@@ -5,7 +5,7 @@ class RhosyncConsole::Server
|
|
5
5
|
session[:login] = params[:login]
|
6
6
|
session[:errors] = nil
|
7
7
|
|
8
|
-
verify_presence_of :server, "Server is not provaided."
|
8
|
+
#verify_presence_of :server, "Server is not provaided."
|
9
9
|
verify_presence_of :login, "Login is not provaided."
|
10
10
|
|
11
11
|
unless session[:errors]
|
@@ -1,110 +1,184 @@
|
|
1
1
|
require 'rest_client'
|
2
|
+
path = File.join(File.dirname(__FILE__),'..','..')
|
3
|
+
$:.unshift path
|
4
|
+
require 'rhosync'
|
5
|
+
include Rhosync
|
2
6
|
|
3
7
|
module RhosyncApi
|
4
8
|
class << self
|
5
9
|
|
6
10
|
def get_token(server,login,password)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
if directcall?(server)
|
12
|
+
Server.get_api_token(nil,User.authenticate(login,password))
|
13
|
+
else
|
14
|
+
cookie = login(server,login,password)
|
15
|
+
RestClient.post("#{server}/api/get_api_token",'',{:cookies => cookie})
|
16
|
+
end
|
12
17
|
end
|
13
18
|
|
14
19
|
def list_users(server,token)
|
15
|
-
|
16
|
-
|
20
|
+
if directcall?(server) and verify_token(token)
|
21
|
+
JSON.parse(Server.list_users(nil,api_user(token)))
|
22
|
+
else
|
23
|
+
JSON.parse(RestClient.post("#{server}/api/list_users",
|
24
|
+
{:api_token => token}.to_json, :content_type => :json).body)
|
25
|
+
end
|
17
26
|
end
|
18
27
|
|
19
28
|
def create_user(server,token,login,password)
|
20
|
-
|
21
|
-
{:
|
22
|
-
|
29
|
+
if directcall?(server) and verify_token(token)
|
30
|
+
Server.create_user({:attributes => {'login' => login, 'password' => password}},nil)
|
31
|
+
else
|
32
|
+
RestClient.post("#{server}/api/create_user",
|
33
|
+
{:api_token => token,:attributes => {:login => login, :password => password}}.to_json,
|
34
|
+
:content_type => :json)
|
35
|
+
end
|
23
36
|
end
|
24
37
|
|
25
38
|
def delete_user(server,token,user_id)
|
26
|
-
|
27
|
-
{:
|
28
|
-
|
39
|
+
if directcall?(server) and verify_token(token)
|
40
|
+
Server.delete_user({:user_id => user_id},nil)
|
41
|
+
else
|
42
|
+
RestClient.post("#{server}/api/delete_user",
|
43
|
+
{:api_token => token, :user_id => user_id}.to_json,
|
44
|
+
:content_type => :json)
|
45
|
+
end
|
29
46
|
end
|
30
47
|
|
31
48
|
def list_clients(server,token,user_id)
|
32
|
-
|
33
|
-
{:
|
49
|
+
if directcall?(server) and verify_token(token)
|
50
|
+
JSON.parse(Server.list_clients({:user_id => user_id},nil))
|
51
|
+
else
|
52
|
+
JSON.parse(RestClient.post("#{server}/api/list_clients",
|
53
|
+
{:api_token => token, :user_id => user_id}.to_json, :content_type => :json).body)
|
54
|
+
end
|
34
55
|
end
|
35
56
|
|
36
57
|
def create_client(server,token,user_id)
|
37
|
-
|
38
|
-
{:
|
39
|
-
|
58
|
+
if directcall?(server) and verify_token(token)
|
59
|
+
Server.create_client({:user_id => user_id},nil)
|
60
|
+
else
|
61
|
+
RestClient.post("#{server}/api/create_client",
|
62
|
+
{:api_token => token, :user_id => user_id}.to_json,
|
63
|
+
:content_type => :json).body
|
64
|
+
end
|
40
65
|
end
|
41
66
|
|
42
67
|
def delete_client(server,token,user_id,client_id)
|
43
|
-
|
44
|
-
{:
|
45
|
-
|
68
|
+
if directcall?(server) and verify_token(token)
|
69
|
+
Server.delete_client({:user_id => user_id,:client_id => client_id},nil)
|
70
|
+
else
|
71
|
+
RestClient.post("#{server}/api/delete_client",
|
72
|
+
{:api_token => token, :user_id => user_id,
|
73
|
+
:client_id => client_id}.to_json, :content_type => :json)
|
74
|
+
end
|
46
75
|
end
|
47
76
|
|
48
77
|
def get_client_params(server,token,client_id)
|
49
|
-
|
50
|
-
{:
|
78
|
+
if directcall?(server) and verify_token(token)
|
79
|
+
JSON.parse(Server.get_client_params({:client_id => client_id},nil))
|
80
|
+
else
|
81
|
+
JSON.parse(RestClient.post("#{server}/api/get_client_params",
|
82
|
+
{:api_token => token, :client_id => client_id}.to_json, :content_type => :json).body)
|
83
|
+
end
|
51
84
|
end
|
52
85
|
|
53
|
-
def list_sources(server,token,partition='all')
|
54
|
-
|
55
|
-
{:
|
86
|
+
def list_sources(server,token,partition='all')
|
87
|
+
if directcall?(server) and verify_token(token)
|
88
|
+
JSON.parse(Server.list_sources({:partition_type => partition},nil))
|
89
|
+
else
|
90
|
+
JSON.parse(RestClient.post("#{server}/api/list_sources",
|
91
|
+
{:api_token => token, :partition_type => partition}.to_json, :content_type => :json).body)
|
92
|
+
end
|
56
93
|
end
|
57
94
|
|
58
95
|
def get_source_params(server,token,source_id)
|
59
|
-
|
60
|
-
{:
|
96
|
+
if directcall?(server) and verify_token(token)
|
97
|
+
JSON.parse(Server.get_source_params({:source_id => source_id},nil))
|
98
|
+
else
|
99
|
+
JSON.parse(RestClient.post("#{server}/api/get_source_params",
|
100
|
+
{:api_token => token, :source_id => source_id}.to_json, :content_type => :json).body)
|
101
|
+
end
|
61
102
|
end
|
62
103
|
|
63
104
|
def list_source_docs(server,token,source_id,user_id='*')
|
64
|
-
|
65
|
-
{:
|
105
|
+
if directcall?(server) and verify_token(token)
|
106
|
+
JSON.parse(Server.list_source_docs({:source_id => source_id, :user_id => user_id},nil))
|
107
|
+
else
|
108
|
+
JSON.parse(RestClient.post("#{server}/api/list_source_docs",
|
109
|
+
{:api_token => token, :source_id => source_id, :user_id => user_id}.to_json, :content_type => :json).body)
|
110
|
+
end
|
66
111
|
end
|
67
112
|
|
68
113
|
def list_client_docs(server,token,source_id,client_id)
|
69
|
-
|
70
|
-
{:
|
114
|
+
if directcall?(server) and verify_token(token)
|
115
|
+
JSON.parse(Server.list_client_docs({:source_id => source_id, :client_id => client_id},nil))
|
116
|
+
else
|
117
|
+
JSON.parse(RestClient.post("#{server}/api/list_client_docs",
|
118
|
+
{:api_token => token, :source_id => source_id, :client_id => client_id}.to_json, :content_type => :json).body)
|
119
|
+
end
|
71
120
|
end
|
72
121
|
|
73
122
|
#TODO: figure out data_type programmatically
|
74
123
|
def get_db_doc(server,token,doc,data_type='')
|
75
|
-
res =
|
76
|
-
|
124
|
+
res = ""
|
125
|
+
if directcall?(server) and verify_token(token)
|
126
|
+
res = Server.get_db_doc({:doc => doc, :data_type => data_type},nil)
|
127
|
+
else
|
128
|
+
res = RestClient.post("#{server}/api/get_db_doc",
|
129
|
+
{:api_token => token, :doc => doc, :data_type => data_type}.to_json, :content_type => :json).body
|
130
|
+
end
|
77
131
|
data_type=='' ? JSON.parse(res) : res
|
78
132
|
end
|
79
133
|
|
80
134
|
#TODO: figure out data_type programmatically
|
81
135
|
def set_db_doc(server,token,doc,data={},data_type='')
|
82
|
-
|
83
|
-
|
136
|
+
if directcall?(server) and verify_token(token)
|
137
|
+
Server.set_db_doc({:doc => doc, :data => data, :data_type => data_type},nil)
|
138
|
+
else
|
139
|
+
RestClient.post("#{server}/api/set_db_doc",
|
140
|
+
{:api_token => token, :doc => doc, :data => data, :data_type => data_type}.to_json, :content_type => :json)
|
141
|
+
end
|
84
142
|
end
|
85
143
|
|
86
144
|
def reset(server,token)
|
87
|
-
|
88
|
-
{:api_token => token}
|
145
|
+
if directcall?(server) and verify_token(token)
|
146
|
+
Server.reset({:api_token => token},api_user(token))
|
147
|
+
else
|
148
|
+
RestClient.post("#{server}/api/reset",
|
149
|
+
{:api_token => token}.to_json, :content_type => :json)
|
150
|
+
end
|
89
151
|
end
|
90
152
|
|
91
153
|
def ping(server,token,user_id,params)
|
92
|
-
ping_params = {
|
93
|
-
[:message,:badge,:sound,:vibrate,:sources].each do |part|
|
154
|
+
ping_params = {'api_token' => token, 'user_id' => user_id}
|
155
|
+
[:message,:badge,:sound,:vibrate,:sources,:async].each do |part|
|
156
|
+
part = part.to_s
|
94
157
|
ping_params.merge!(part => params[part]) if params[part]
|
95
158
|
end
|
96
|
-
|
159
|
+
if directcall?(server) and verify_token(token)
|
160
|
+
Server.ping(ping_params,nil)
|
161
|
+
else
|
162
|
+
RestClient.post("#{server}/api/ping",ping_params.to_json, :content_type => :json)
|
163
|
+
end
|
97
164
|
end
|
98
165
|
|
99
166
|
def get_license_info(server,token)
|
100
|
-
|
101
|
-
|
167
|
+
if directcall?(server) and verify_token(token)
|
168
|
+
JSON.parse(Server.get_license_info(nil,nil))
|
169
|
+
else
|
170
|
+
JSON.parse(RestClient.post("#{server}/api/get_license_info",
|
171
|
+
{:api_token => token}.to_json, :content_type => :json).body)
|
172
|
+
end
|
102
173
|
end
|
103
174
|
|
104
175
|
private
|
105
176
|
|
106
177
|
# TODO: Kill this code when rest-client properly
|
107
178
|
# escapes cookie strings on MAC/LINUX AND WINDOWS
|
179
|
+
# res = RestClient.post("#{server}/login",
|
180
|
+
# {:login => login, :password => password}.to_json, :content_type => :json)
|
181
|
+
# RestClient.post("#{server}/api/get_api_token",'',{:cookies => res.cookies})
|
108
182
|
def login(server,login,password)
|
109
183
|
uri = URI.parse(server)
|
110
184
|
http = Net::HTTP.new(uri.host,uri.port)
|
@@ -114,5 +188,26 @@ module RhosyncApi
|
|
114
188
|
cookie = res.response['set-cookie'].split('; ')[0].split('=')
|
115
189
|
{cookie[0] => cookie[1]}
|
116
190
|
end
|
191
|
+
|
192
|
+
def directcall?(server)
|
193
|
+
server.nil? or server.length == 0
|
194
|
+
end
|
195
|
+
|
196
|
+
def api_user(token)
|
197
|
+
ApiToken.load(token).user
|
198
|
+
end
|
199
|
+
|
200
|
+
def verify_token(token)
|
201
|
+
raise ApiException.new(422, "Invalid/missing API user") unless api_user(token); true
|
202
|
+
end
|
117
203
|
end
|
118
|
-
|
204
|
+
|
205
|
+
class Server
|
206
|
+
def self.api(method_name,&block)
|
207
|
+
self.class.send(:define_method, method_name, &block)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
include RhosyncApi
|
213
|
+
Dir[File.join(File.dirname(__FILE__),'..','api','**','*.rb')].each { |api| load api }
|
data/lib/rhosync/model.rb
CHANGED
@@ -378,7 +378,12 @@ module Rhosync
|
|
378
378
|
alias_method :member?, :include?
|
379
379
|
|
380
380
|
def members
|
381
|
-
@redis.smembers(@name)
|
381
|
+
members = @redis.smembers(@name)
|
382
|
+
if members
|
383
|
+
members.map { |v| @marshal.load(v) }
|
384
|
+
else
|
385
|
+
[]
|
386
|
+
end
|
382
387
|
end
|
383
388
|
|
384
389
|
def intersect(*keys)
|
data/lib/rhosync/store.rb
CHANGED
@@ -13,7 +13,7 @@ module Rhosync
|
|
13
13
|
def create(server=nil)
|
14
14
|
@@db ||= _get_redis(server)
|
15
15
|
raise "Error connecting to Redis store." unless @@db and
|
16
|
-
(@@db.is_a?(Redis) or @@db.is_a?(Redis::Client)
|
16
|
+
(@@db.is_a?(Redis) or @@db.is_a?(Redis::Client))
|
17
17
|
end
|
18
18
|
|
19
19
|
# Adds set with given data, replaces existing set
|
@@ -24,19 +24,19 @@ module Rhosync
|
|
24
24
|
flash_data(dockey) unless append
|
25
25
|
# Inserts a hash or array
|
26
26
|
if data.is_a?(Hash)
|
27
|
-
@@db.pipelined do
|
27
|
+
@@db.pipelined do
|
28
28
|
data.each do |key,value|
|
29
29
|
value.each do |attrib,value|
|
30
30
|
unless _is_reserved?(attrib,value)
|
31
|
-
|
31
|
+
@@db.sadd(dockey,setelement(key,attrib,value))
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
36
|
else
|
37
|
-
@@db.pipelined do
|
37
|
+
@@db.pipelined do
|
38
38
|
data.each do |value|
|
39
|
-
|
39
|
+
@@db.sadd(dockey,value)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -61,7 +61,8 @@ module Rhosync
|
|
61
61
|
def get_data(dockey,type=Hash)
|
62
62
|
res = type == Hash ? {} : []
|
63
63
|
if dockey
|
64
|
-
@@db.smembers(dockey)
|
64
|
+
members = @@db.smembers(dockey)
|
65
|
+
members.each do |element|
|
65
66
|
if type == Hash
|
66
67
|
key,attrib,value = getelement(element)
|
67
68
|
res[key] = {} unless res[key]
|
@@ -69,7 +70,7 @@ module Rhosync
|
|
69
70
|
else
|
70
71
|
res << element
|
71
72
|
end
|
72
|
-
end
|
73
|
+
end if members
|
73
74
|
res
|
74
75
|
end
|
75
76
|
end
|
@@ -101,10 +102,10 @@ module Rhosync
|
|
101
102
|
# Deletes data from a given doctype,source,user
|
102
103
|
def delete_data(dockey,data={})
|
103
104
|
if dockey and data
|
104
|
-
@@db.pipelined do
|
105
|
+
@@db.pipelined do
|
105
106
|
data.each do |key,value|
|
106
107
|
value.each do |attrib,val|
|
107
|
-
|
108
|
+
@@db.srem(dockey,setelement(key,attrib,val))
|
108
109
|
end
|
109
110
|
end
|
110
111
|
end
|
@@ -139,18 +140,19 @@ module Rhosync
|
|
139
140
|
|
140
141
|
def get_lock(dockey,timeout=0)
|
141
142
|
lock_key = _lock_key(dockey)
|
142
|
-
current_time = Time.now.to_i
|
143
|
-
|
144
|
-
|
143
|
+
current_time = Time.now.to_i
|
144
|
+
ts = current_time+timeout+1
|
145
|
+
if not @@db.setnx(lock_key,ts)
|
146
|
+
loop do
|
145
147
|
if @@db.get(lock_key).to_i <= current_time and
|
146
|
-
|
148
|
+
@@db.getset(lock_key,ts).to_i <= current_time
|
147
149
|
break
|
148
150
|
end
|
149
151
|
sleep(1)
|
150
152
|
current_time = Time.now.to_i
|
151
153
|
end
|
152
154
|
end
|
153
|
-
|
155
|
+
return ts
|
154
156
|
end
|
155
157
|
|
156
158
|
# Due to redis bug #140, setnx always returns true so this doesn't work
|
@@ -179,12 +181,12 @@ module Rhosync
|
|
179
181
|
|
180
182
|
private
|
181
183
|
def _get_redis(server=nil)
|
182
|
-
if
|
184
|
+
if ENV[REDIS_URL]
|
185
|
+
Redis.connect(:url => ENV[REDIS_URL])
|
186
|
+
elsif server and server.is_a?(String)
|
183
187
|
host,port,db,password = server.split(':')
|
184
188
|
Redis.new(:thread_safe => true, :host => host,
|
185
189
|
:port => port, :db => db, :password => password)
|
186
|
-
elsif server and server.is_a?(Array)
|
187
|
-
Redis::Distributed.new :hosts => server
|
188
190
|
else
|
189
191
|
Redis.new(:thread_safe => true)
|
190
192
|
end
|
data/lib/rhosync/version.rb
CHANGED
data/lib/rhosync.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'redis'
|
2
|
-
require 'redis/distributed'
|
3
2
|
require 'json'
|
4
3
|
require 'base64'
|
5
4
|
require 'zip/zip'
|
@@ -23,6 +22,8 @@ require 'rhosync/rho_indifferent_access'
|
|
23
22
|
require 'rhosync/jobs/source_job'
|
24
23
|
require 'rhosync/jobs/ping_job'
|
25
24
|
require 'rhosync/bulk_data'
|
25
|
+
|
26
|
+
REDIS_URL = 'REDIS' unless defined? REDIS_URL
|
26
27
|
|
27
28
|
# Various module utilities for the store
|
28
29
|
module Rhosync
|
data/spec/api/api_helper.rb
CHANGED
@@ -17,7 +17,7 @@ describe "ApiHelper", :shared => true do
|
|
17
17
|
Rhosync.bootstrap(get_testapp_path) do |rhosync|
|
18
18
|
rhosync.vendor_directory = File.join(rhosync.base_directory,'..','..','..','vendor')
|
19
19
|
end
|
20
|
-
Server.set(
|
20
|
+
Rhosync::Server.set(
|
21
21
|
:environment => :test,
|
22
22
|
:run => false,
|
23
23
|
:secret => "secure!"
|
@@ -26,7 +26,7 @@ describe "ApiHelper", :shared => true do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def app
|
29
|
-
@app ||= Server.new
|
29
|
+
@app ||= Rhosync::Server.new
|
30
30
|
end
|
31
31
|
|
32
32
|
it_should_behave_like "DBObjectsHelper"
|