social_stream-presence 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ rsa_keys/*
@@ -1,5 +1,7 @@
1
1
  class XmppController < ApplicationController
2
2
 
3
+ before_filter :authorization, :only => [:setConnection, :unsetConecction, :setPresence, :unsetPresence, :resetConnection, :synchronizePresence ]
4
+
3
5
  #Mapping XMPP Standar Status to Social Stream Chat Status
4
6
  STATUS = {
5
7
  '' => 'available',
@@ -10,14 +12,12 @@ class XmppController < ApplicationController
10
12
  }
11
13
 
12
14
 
13
- #API METHODS
15
+ ##############################
16
+ ########## REST API ##########
17
+ ##############################
14
18
 
15
- def setConnection
16
- unless authorization
17
- render :text => "Authorization error"
18
- return
19
- end
20
-
19
+ def setConnection
20
+ params = @dparams
21
21
  user = User.find_by_slug(params[:name])
22
22
 
23
23
  if user && !user.connected
@@ -28,16 +28,12 @@ class XmppController < ApplicationController
28
28
  return
29
29
  end
30
30
 
31
- render :text => "Error"
31
+ render :text => "Ok: The user was already connected"
32
32
  end
33
33
 
34
34
 
35
35
  def unsetConecction
36
- unless authorization
37
- render :text => "Authorization error"
38
- return
39
- end
40
-
36
+ params = @dparams
41
37
  user = User.find_by_slug(params[:name])
42
38
 
43
39
  if user && user.connected
@@ -47,16 +43,12 @@ class XmppController < ApplicationController
47
43
  return
48
44
  end
49
45
 
50
- render :text => "User not connected"
46
+ render :text => "Ok: The user was already disconnected"
51
47
  end
52
48
 
53
49
 
54
- def setPresence
55
- unless authorization
56
- render :text => "Authorization error"
57
- return
58
- end
59
-
50
+ def setPresence
51
+ params = @dparams
60
52
  user = User.find_by_slug(params[:name])
61
53
  status = params[:status]
62
54
 
@@ -65,20 +57,16 @@ class XmppController < ApplicationController
65
57
  user.connected = true
66
58
  user.save!
67
59
  end
68
- render :text => 'Status changed'
60
+ render :text => "Ok: Status changed"
69
61
  else
70
- render :text => 'Status not changed'
62
+ render :text => "Ok: Status not changed"
71
63
  end
72
64
 
73
65
  end
74
66
 
75
67
 
76
- def unsetPresence
77
- unless authorization
78
- render :text => "Authorization error"
79
- return
80
- end
81
-
68
+ def unsetPresence
69
+ params = @dparams
82
70
  user = User.find_by_slug(params[:name])
83
71
 
84
72
  if user && user.connected
@@ -88,44 +76,36 @@ class XmppController < ApplicationController
88
76
  return
89
77
  end
90
78
 
91
- render :text => "User not connected"
79
+ render :text => "Ok: The user was already disconnected"
92
80
  end
93
81
 
94
82
 
95
83
  def resetConnection
96
- unless authorization
97
- render :text => "Authorization error"
98
- return
99
- end
100
-
101
84
  SocialStream::Presence::XmppServerOrder::resetPresence
102
-
103
85
  render :text => "Ok"
104
86
  end
105
87
 
106
88
 
107
- def synchronizePresence
108
- unless authorization
109
- render :text => "Authorization error"
89
+ def synchronizePresence
90
+ params = @dparams
91
+
92
+ #Work without encrypted params
93
+ if params[:name] == nil or params[:name].empty? or params[:name]==""
94
+ render :text => "Ok: No users received"
110
95
  return
111
- end
112
-
113
- #Actual connected users
114
- user_slugs = params[:name]
96
+ end
115
97
 
98
+ #Actual connected users
99
+ user_slugs = params[:name].split(",")
116
100
  SocialStream::Presence::XmppServerOrder::synchronizePresenceForSlugs(user_slugs)
117
-
118
- render :text => "ok"
119
- end
120
-
121
-
122
- def authorization
123
- return params[:password] == SocialStream::Presence.xmpp_server_password
101
+ render :text => "Ok"
124
102
  end
125
103
 
126
104
 
127
- def chatWindow
128
-
105
+
106
+ #OPEN METHODS
107
+
108
+ def chatWindow
129
109
  if current_user and current_user.chat_enabled and (params[:userConnected]=="true")
130
110
  render :partial => 'chat/contacts'
131
111
  elsif current_user and current_user.chat_enabled
@@ -183,7 +163,7 @@ class XmppController < ApplicationController
183
163
  private
184
164
 
185
165
  def setStatus(user,status)
186
- if user and status and user.status != status and validStatus(status)
166
+ if user and status and validStatus(status) and user.status != STATUS[status]
187
167
  user.status = STATUS[status]
188
168
  user.save!
189
169
  return true
@@ -195,4 +175,13 @@ class XmppController < ApplicationController
195
175
  return STATUS.keys.include?(status)
196
176
  end
197
177
 
178
+
179
+ #Authorization to use REST API
180
+ def authorization
181
+ unless SocialStream::Presence::XmppServerOrder::authorization(params)
182
+ render :text => "Authorization error"
183
+ end
184
+ @dparams = SocialStream::Presence::XmppServerOrder::decryptParams(params)
185
+ end
186
+
198
187
  end
@@ -24,7 +24,8 @@ cookie_name=_rails_server_cookie
24
24
 
25
25
  #Ejabberd Server Password
26
26
  ejabberd_password=password
27
-
27
+ #True to enable REST API Security
28
+ secure_rest_api=false
28
29
 
29
30
  #Emanagement configuration
30
31
  ejabberd_server_user=ejabberd
Binary file
@@ -1,9 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
- #Reset Connection Script
2
+ #Rest Api Client Script
3
+ #Version: 13-12-2011
3
4
  #@author Aldo
4
5
 
6
+
5
7
  require 'logger'
6
8
  require 'rest_client'
9
+ require 'openssl'
10
+ require 'digest/md5'
11
+
7
12
 
8
13
  path = "/var/log/ejabberd/scripts.log"
9
14
  file = File.open(path, File::WRONLY | File::APPEND | File::CREAT)
@@ -25,31 +30,268 @@ def getOption(option)
25
30
  return "Undefined"
26
31
  end
27
32
 
28
- $url = "http://" + getOption("web_domain=") + "/xmpp/resetConnection"
33
+ #Constants
34
+ $secure_rest_api = getOption("secure_rest_api=")
29
35
  $pass = getOption("ejabberd_password=")
36
+ $scripts_path = getOption("scripts_path=")
37
+ $script_title = "Reset Connection script"
38
+
39
+
40
+ def log(title,text)
41
+ $logger.info title + ": " + text
42
+ end
43
+
44
+ def getMethodName
45
+ caller[0] =~ /`(.*?)'/
46
+ $1
47
+ end
48
+
49
+
50
+ #####################
51
+ ##### Example #####
52
+ #####################
53
+ #def myHook(param1,param2)
54
+ # log(getMethodName,"(My message: #{param1},#{param2})")
55
+ # url = "http://" + getOption("web_domain=") + "/xmpp/hookRoute"
56
+
57
+ # params = {}
58
+ # encrypted_params = {}
59
+ # #Add params to sent in clear
60
+ # params[:param1_in_server]=param1
61
+ # #Add params to sent cipher
62
+ # encrypted_params[:param2_in_server]=param2
63
+
64
+ # return [getMethodName,generic_api_call(url,params,encrypted_params)]
65
+ #end
66
+
67
+ def setConnection(username)
68
+ log($script_title,"#{getMethodName}(#{username})")
69
+ url = "http://" + getOption("web_domain=") + "/xmpp/setConnection"
70
+
71
+ params = {}
72
+ encrypted_params = {}
73
+ encrypted_params[:name]=username
74
+
75
+ return [getMethodName,generic_api_call(url,params,encrypted_params)]
76
+ end
77
+
78
+
79
+ def unsetConnection(username)
80
+ log($script_title,"#{getMethodName}(#{username})")
81
+ url = "http://" + getOption("web_domain=") + "/xmpp/unsetConnection"
82
+
83
+ params = {}
84
+ encrypted_params = {}
85
+ encrypted_params[:name]=username
30
86
 
87
+ return [getMethodName,generic_api_call(url,params,encrypted_params)]
88
+ end
89
+
90
+
91
+ def setPresence(username,status)
92
+ log($script_title,"#{getMethodName}(#{username},#{status})")
93
+ url = "http://" + getOption("web_domain=") + "/xmpp/setPresence"
94
+
95
+ params = {}
96
+ encrypted_params = {}
97
+ encrypted_params[:name]=username
98
+ encrypted_params[:status]=status
99
+
100
+ return [getMethodName,generic_api_call(url,params,encrypted_params)]
101
+ end
102
+
103
+
104
+ def unsetPresence(username)
105
+ log($script_title,"#{getMethodName}(#{username})")
106
+ url = "http://" + getOption("web_domain=") + "/xmpp/unsetPresence"
107
+
108
+ params = {}
109
+ encrypted_params = {}
110
+ encrypted_params[:name]=username
31
111
 
32
- def log(text)
33
- $logger.info "Reset Connection Script: " + text
112
+ return [getMethodName,generic_api_call(url,params,encrypted_params)]
34
113
  end
35
114
 
36
115
 
37
116
  def resetConnection()
117
+ log($script_title,"Call #{getMethodName}()")
118
+ url = "http://" + getOption("web_domain=") + "/xmpp/resetConnection"
119
+
120
+ params = {}
121
+ encrypted_params = {}
122
+
123
+ return [getMethodName,generic_api_call(url,params,encrypted_params)]
124
+ end
125
+
126
+
127
+ def synchronize()
128
+ log($script_title,"Call #{getMethodName}()")
129
+ url = "http://" + getOption("web_domain=") + "/xmpp/synchronizePresence"
130
+
131
+
132
+ #Get connected users using Emanagement
133
+ users = []
134
+ command = $scripts_path + "/emanagement getConnectedUsers"
135
+ output = %x[#{command}]
136
+ sessions = output.split("\n")
137
+
138
+ sessions.each do |session|
139
+ users << session.split("@")[0]
140
+ end
141
+ #Finish
142
+
143
+
144
+ #In this cases users always will be sent in clear (not cipher)
145
+ #(Too much data to cipher)
146
+ #Anyway, we must to build the hash to pass the authentication
147
+ params = {}
148
+ encrypted_params = {}
149
+ params[:name]=users.join(",")
150
+
151
+ return [getMethodName,generic_api_call(url,params,encrypted_params)]
152
+ end
153
+
154
+
155
+
156
+ #Params must include the password and all the parameters to be sent in clear.
157
+ #Anyway, If "secure_rest_api" is disable, encrypted_params will be send in clear.
158
+ def generic_api_call(url,params,encrypted_params)
159
+
38
160
  begin
39
- RestClient.post($url, :password => $pass)
40
- return true
161
+ unless params
162
+ params = {}
163
+ end
164
+
165
+ unless encrypted_params
166
+ encrypted_params = {}
167
+ end
168
+
169
+ params[:password]=$pass
170
+
171
+ response=sendHttpRequest(url,params,encrypted_params)
172
+ puts response.body
173
+
174
+ if response.body.include?("Ok")
175
+ return true
176
+ else
177
+ return false
178
+ end
179
+
41
180
  rescue => e
42
- log("#{e.class.name}: #{e.message}")
181
+ log($script_title,"#{e.class.name}: #{e.message}")
182
+ puts("#{e.class.name}: #{e.message}")
43
183
  return false
44
184
  end
45
185
  end
46
186
 
47
- if (resetConnection())
48
- puts "Reset Connection [OK]"
49
- log( "Reset Connection [OK]" )
50
- else
51
- puts "Reset Connection [FAIL]"
52
- log( "Reset Connection [FAIL]" )
187
+
188
+ #Send HTTP Request to Social Stream Presence API
189
+ def sendHttpRequest(url,params,encrypted_params)
190
+
191
+ unless params[:password]
192
+ return "params[:password] required in sendHttpRequest";
193
+ end
194
+
195
+
196
+ if $secure_rest_api == "true"
197
+ xmpp_private_key_path = $scripts_path + "/rsa_keys/xmpp_rsa_key_private.pem";
198
+ web_public_key_path = $scripts_path + "/rsa_keys/web_rsa_key_public.pem";
199
+ xmpp_private_key = OpenSSL::PKey::RSA.new(File.read(xmpp_private_key_path))
200
+ web_public_key = OpenSSL::PKey::RSA.new(File.read(web_public_key_path))
201
+
202
+ request_params = {};
203
+
204
+ #Copy non encypted params
205
+ params.each do |key,value|
206
+ unless key.to_s == "password"
207
+ request_params[key] = value
208
+ end
209
+ end
210
+
211
+ #Include encrypted params
212
+ if encrypted_params and encrypted_params.empty? == false
213
+ request_params[:encrypted_params] = web_public_key.public_encrypt(encrypted_params.to_s)
214
+ end
215
+
216
+ #Generating stamp
217
+ #1 Get constant password
218
+ password = params[:password];
219
+ #2 Generating timestamp
220
+ timestamp = Time.now.utc.to_s
221
+ #3 Calculating Hash
222
+ hash = calculateHash(request_params)
223
+
224
+ #Add cipher stamp to the request
225
+ request_params[:password] = xmpp_private_key.private_encrypt(password+"#####"+timestamp+"#####"+hash)
226
+
227
+ #Replace previous params
228
+ params = request_params
229
+ else
230
+ #Non secure mode: send encrypted params in clear
231
+ if encrypted_params
232
+ encrypted_params.each do |key,value|
233
+ params[key] = value
234
+ end
235
+ end
236
+ end
237
+
238
+ response = RestClient.get url, :params => params
239
+ return response
53
240
  end
54
241
 
55
242
 
243
+ def calculateHash(request_params)
244
+ unless request_params
245
+ request_params = {};
246
+ end
247
+
248
+ hash = "";
249
+ request_params.each do |key,value|
250
+ hash = hash + key.to_s + value.to_s
251
+ end
252
+ return Digest::MD5.hexdigest(hash)
253
+ end
254
+
255
+
256
+
257
+
258
+ def invokeApiCall(method,args)
259
+ length = args.length;
260
+ case length
261
+ when 0
262
+ return send(method)
263
+ when 1
264
+ return send(method,args[0])
265
+ when 2
266
+ return send(method,args[0],args[1])
267
+ when 3
268
+ return send(method,args[0],args[1],args[2])
269
+ when 4
270
+ return send(method,args[0],args[1],args[2],args[3])
271
+ else
272
+ return send(method,args)
273
+ end
274
+ end
275
+
276
+
277
+ #Main Program
278
+
279
+ begin
280
+
281
+ args = []
282
+ method = "resetConnection";
283
+
284
+ if (response = invokeApiCall(method, args) and response[1])
285
+ puts $script_title + ": #{response[0]} [OK]"
286
+ log( $script_title , "#{response[0]} [OK]" )
287
+ else
288
+ puts $script_title + ": #{response[0]} [FAIL]"
289
+ log( $script_title , "#{response[0]} [FAIL]" )
290
+ end
291
+
292
+ rescue => e
293
+ log($script_title,"#{e.class.name}: #{e.message}")
294
+ puts("#{e.class.name}: #{e.message}")
295
+ exit 1
296
+ end
297
+