automate-em 0.0.1 → 0.0.2
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/app/assets/javascripts/jquery.automate.js +439 -0
- data/app/controllers/tokens_controller.rb +99 -0
- data/app/models/setting.rb +2 -2
- data/config/routes.rb +12 -0
- data/lib/automate-em/core/modules.rb +23 -16
- data/lib/automate-em/core/system.rb +1 -1
- data/lib/automate-em/engine.rb +1 -0
- data/lib/automate-em/version.rb +1 -1
- data/lib/generators/module/module_generator.rb +3 -3
- data/test/functional/tokens_controller_test.rb +7 -0
- data/test/unit/helpers/tokens_helper_test.rb +4 -0
- metadata +9 -2
@@ -0,0 +1,439 @@
|
|
1
|
+
/**
|
2
|
+
* ACA Control jQuery Interface Library
|
3
|
+
* Simplifies communication with an ACA Control server when using jQuery
|
4
|
+
*
|
5
|
+
* Copyright (c) 2011 Advanced Control and Acoustics.
|
6
|
+
*
|
7
|
+
* @author Stephen von Takach <steve@advancedcontrol.com.au>
|
8
|
+
* @copyright 2011 advancedcontrol.com.au
|
9
|
+
*
|
10
|
+
* --- Usage ---
|
11
|
+
* Connecting to an ACA Control Server:
|
12
|
+
var controller = new AutomateEm.EventsDispatcher({
|
13
|
+
url: 'http://my.control.server.org:8080/',
|
14
|
+
one_time_key: '/key/url'
|
15
|
+
});
|
16
|
+
|
17
|
+
* Binding to an event:
|
18
|
+
controller.bind('some_event', function(data){
|
19
|
+
alert(data.name + ' says: ' + data.message)
|
20
|
+
});
|
21
|
+
|
22
|
+
* Sending a command to the server:
|
23
|
+
controller.send('Module.function', "item1", ['item', 2], {item:3}, 4, 5.0, ...);
|
24
|
+
|
25
|
+
*
|
26
|
+
**/
|
27
|
+
|
28
|
+
|
29
|
+
var AutomateEm = {
|
30
|
+
Off: false,
|
31
|
+
On: true,
|
32
|
+
Controllers: [], // So we can inspect all instances
|
33
|
+
EventsDispatcher: function (options) {
|
34
|
+
//
|
35
|
+
// options contains: url, system calls, system
|
36
|
+
//
|
37
|
+
var config = {
|
38
|
+
servers: null, // List of ACA Control Servers in priority order
|
39
|
+
system: null, // The system we are connecting to and authentication details for re-connects
|
40
|
+
auto_auth: null, // Are we using the manifest authentication system
|
41
|
+
idle_update: null, // Do we want to auto-update the interface when it is idle
|
42
|
+
forced_update: null,// Update the interface as soon as possible
|
43
|
+
},
|
44
|
+
state ={
|
45
|
+
connection: null, // Base web socket
|
46
|
+
connected: true, // Are we currently connected (initialised to true so that any initial failure is triggered)
|
47
|
+
ready: false, // Is the server ready for bindings and commands
|
48
|
+
polling: false, // Are we polling to remain connected when there is little activity
|
49
|
+
resume: false, // The reference to the resume timer
|
50
|
+
updater: false, // The reference to the update timer
|
51
|
+
offline: false // The system has indicated that it is offline
|
52
|
+
},
|
53
|
+
bindings = {},
|
54
|
+
system_calls = {
|
55
|
+
open: true, // Connection to the server has been made
|
56
|
+
close: true, // Connection to the server was closed or lost
|
57
|
+
ls: true, // List of control systems available to the current user (paginated)
|
58
|
+
ready: true, // Remote System is ready for bindings
|
59
|
+
authenticate: true, // Authentication required
|
60
|
+
system: true, // Please select a system
|
61
|
+
pong: true, // System is idle
|
62
|
+
offline: true // System is offline (slow down re-connect periods)
|
63
|
+
},
|
64
|
+
$this = this;
|
65
|
+
$.extend(config, options);
|
66
|
+
this.config = config; // Allow external access
|
67
|
+
|
68
|
+
|
69
|
+
//
|
70
|
+
// Sends a command to the server in the appropriate format
|
71
|
+
//
|
72
|
+
var send = function (command_name) {
|
73
|
+
var payload = JSON.stringify({ command: command_name, data: Array.prototype.slice.call( arguments, 1 ) });
|
74
|
+
// Array.prototype.slice.call( arguments, 1 ) gets all the arguments - the first in an array
|
75
|
+
|
76
|
+
if (state.connection != null && state.connection.readyState == state.connection.OPEN) {
|
77
|
+
state.connection.send(payload); // <= send JSON data to socket server
|
78
|
+
set_poll(); // Reset polling
|
79
|
+
}
|
80
|
+
|
81
|
+
return $this; // chainable
|
82
|
+
};
|
83
|
+
this.send = send;
|
84
|
+
|
85
|
+
//
|
86
|
+
// Requests to recieve notifications of a value change from the server
|
87
|
+
// Triggers the functions passed in when the server informs us of an update
|
88
|
+
//
|
89
|
+
this.bind = function (events, func) {
|
90
|
+
if(!!func) {
|
91
|
+
var temp = {};
|
92
|
+
temp[events] = func;
|
93
|
+
events = temp;
|
94
|
+
}
|
95
|
+
|
96
|
+
jQuery.each( events, function(event_name, callback){
|
97
|
+
bindings[event_name] = bindings[event_name] || [];
|
98
|
+
bindings[event_name].push(callback);
|
99
|
+
|
100
|
+
if (!system_calls[event_name] && state.connection != null && state.connection.readyState == state.connection.OPEN){
|
101
|
+
var args = event_name.split('.');
|
102
|
+
args.splice(0,0, 'register');
|
103
|
+
send.apply( this, args );
|
104
|
+
}
|
105
|
+
});
|
106
|
+
|
107
|
+
return this; // chainable
|
108
|
+
};
|
109
|
+
|
110
|
+
this.is_connected = function(){
|
111
|
+
return state.connected;
|
112
|
+
};
|
113
|
+
|
114
|
+
//
|
115
|
+
// Removes all the callbacks for the event and lets the server know that we
|
116
|
+
// don't want to revieve it anymore.
|
117
|
+
//
|
118
|
+
this.unbind = function (event_name) {
|
119
|
+
delete bindings[event_name];
|
120
|
+
|
121
|
+
if (state.connection != null && state.connection.readyState == state.connection.OPEN){
|
122
|
+
var args = event_name.split('.');
|
123
|
+
args.splice(0,0, 'unregister');
|
124
|
+
send.apply( this, args );
|
125
|
+
}
|
126
|
+
|
127
|
+
return this; // chainable
|
128
|
+
};
|
129
|
+
|
130
|
+
//
|
131
|
+
// The event trigger, calls the registered handlers in order
|
132
|
+
//
|
133
|
+
var trigger = function (event_name, message) {
|
134
|
+
var chain = bindings[event_name];
|
135
|
+
if (chain === undefined) return; // no bindings for this event
|
136
|
+
|
137
|
+
var i, result;
|
138
|
+
for (i = 0; i < chain.length; i = i + 1) {
|
139
|
+
try {
|
140
|
+
result = chain[i](message);
|
141
|
+
if(result === false) // Return false to prevent later bindings
|
142
|
+
break;
|
143
|
+
} catch (err) { } // Catch any user code errors
|
144
|
+
}
|
145
|
+
|
146
|
+
return $this; // chainable
|
147
|
+
};
|
148
|
+
this.trigger = trigger;
|
149
|
+
|
150
|
+
|
151
|
+
//
|
152
|
+
// Polling functions
|
153
|
+
// Only called if no other traffic is being transmitted.
|
154
|
+
//
|
155
|
+
function set_poll(){
|
156
|
+
if(!!state.polling) {
|
157
|
+
clearInterval(state.polling);
|
158
|
+
}
|
159
|
+
state.polling = setInterval(do_poll, 60000); // Maintain the connection by pinging every 1min
|
160
|
+
}
|
161
|
+
|
162
|
+
function do_poll(){
|
163
|
+
if((!!config.idle_update) && updateReady) // Update on idle
|
164
|
+
window.location.reload();
|
165
|
+
else
|
166
|
+
send('ping');
|
167
|
+
}
|
168
|
+
|
169
|
+
|
170
|
+
//
|
171
|
+
// Sets up a new connection to the remote server
|
172
|
+
//
|
173
|
+
function setup_connection() {
|
174
|
+
jQuery.ajax('/tokens/servers', {
|
175
|
+
type: 'GET',
|
176
|
+
dataType: 'json',
|
177
|
+
success: function(data, textStatus, jqXHR){
|
178
|
+
config.servers = data;
|
179
|
+
|
180
|
+
if(!!window.WebSocket)
|
181
|
+
state.connection = new window.WebSocket("ws://" + config.servers[0].hostname + ":81/");
|
182
|
+
else if(!!window.MozWebSocket)
|
183
|
+
state.connection = new window.MozWebSocket("ws://" + config.servers[0].hostname + ":81/");
|
184
|
+
else
|
185
|
+
return;
|
186
|
+
|
187
|
+
// dispatch to the right handlers
|
188
|
+
state.connection.onmessage = function (evt) {
|
189
|
+
var json = JSON.parse(evt.data);
|
190
|
+
|
191
|
+
if (json.event == 'ready') {
|
192
|
+
//
|
193
|
+
// Re-register status events then call ready
|
194
|
+
//
|
195
|
+
for (event_name in bindings) {
|
196
|
+
try {
|
197
|
+
if(!system_calls[event_name]) {
|
198
|
+
var args = event_name.split('.');
|
199
|
+
args.splice(0,0, 'register');
|
200
|
+
send.apply( this, args );
|
201
|
+
}
|
202
|
+
} catch (err) { }
|
203
|
+
}
|
204
|
+
|
205
|
+
set_poll(); // Set the polling to occur
|
206
|
+
}
|
207
|
+
|
208
|
+
//
|
209
|
+
// Trigger callbacks
|
210
|
+
//
|
211
|
+
trigger(json.event, json.data);
|
212
|
+
};
|
213
|
+
|
214
|
+
state.connection.onclose = function () {
|
215
|
+
if (state.connected) {
|
216
|
+
state.connected = false;
|
217
|
+
if(!!state.polling) {
|
218
|
+
clearInterval(state.polling);
|
219
|
+
state.polling = false;
|
220
|
+
}
|
221
|
+
trigger('close');
|
222
|
+
}
|
223
|
+
}
|
224
|
+
state.connection.onopen = function () {
|
225
|
+
state.connected = true; // prevent multiple disconnect triggers
|
226
|
+
trigger('open');
|
227
|
+
}
|
228
|
+
},
|
229
|
+
error: function(jqXHR, textStatus, errorThrown){
|
230
|
+
//
|
231
|
+
// Damn...
|
232
|
+
//
|
233
|
+
;
|
234
|
+
}
|
235
|
+
});
|
236
|
+
}
|
237
|
+
setup_connection();
|
238
|
+
|
239
|
+
|
240
|
+
//
|
241
|
+
// Ensure the connection is resumed if disconnected
|
242
|
+
// We do this in this way for mobile devices when resumed from sleep to ensure they reconnect
|
243
|
+
//
|
244
|
+
function checkResume() {
|
245
|
+
if (state.connection == null || state.connection.readyState == state.connection.CLOSED) {
|
246
|
+
setup_connection();
|
247
|
+
}
|
248
|
+
}
|
249
|
+
state.resume = window.setInterval(checkResume, 1000);
|
250
|
+
AutomateEm.Controllers.push(this);
|
251
|
+
|
252
|
+
|
253
|
+
//
|
254
|
+
// Bind events for automation (first attempt, else fall back to interface for both auth and system)
|
255
|
+
//
|
256
|
+
var authCount = 0,
|
257
|
+
sysCallCount = 0,
|
258
|
+
oneKey;
|
259
|
+
|
260
|
+
this.bind('open', function(){
|
261
|
+
|
262
|
+
authCount = 0;
|
263
|
+
sysCallCount = 0;
|
264
|
+
oneKey = null;
|
265
|
+
|
266
|
+
});
|
267
|
+
|
268
|
+
function getCookie(c_name)
|
269
|
+
{
|
270
|
+
var i,x,y,ARRcookies=document.cookie.split(";");
|
271
|
+
for (i=0;i<ARRcookies.length;i++)
|
272
|
+
{
|
273
|
+
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
|
274
|
+
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
|
275
|
+
x=x.replace(/^\s+|\s+$/g,"");
|
276
|
+
if (x==c_name)
|
277
|
+
{
|
278
|
+
return unescape(y);
|
279
|
+
}
|
280
|
+
}
|
281
|
+
return null;
|
282
|
+
}
|
283
|
+
|
284
|
+
this.bind('authenticate', function(){
|
285
|
+
authCount += 1;
|
286
|
+
|
287
|
+
if(authCount == 1 && (!!config.auto_auth) && (!!config.system)) {
|
288
|
+
oneKey = getCookie('next_key');
|
289
|
+
if(!!oneKey){
|
290
|
+
send("authenticate", oneKey);
|
291
|
+
return false;
|
292
|
+
}
|
293
|
+
}
|
294
|
+
|
295
|
+
authCount += 1;
|
296
|
+
});
|
297
|
+
|
298
|
+
this.bind('system', function(){
|
299
|
+
sysCallCount += 1;
|
300
|
+
|
301
|
+
if(sysCallCount == 1 && config.system !== false) { // 0 == false
|
302
|
+
send("system", config.system);
|
303
|
+
|
304
|
+
return false;
|
305
|
+
} // Auto login failure here will result in a disconnect
|
306
|
+
});
|
307
|
+
|
308
|
+
this.bind('offline', function(){
|
309
|
+
state.offline = true;
|
310
|
+
clearInterval(state.resume);
|
311
|
+
state.resume = window.setInterval(checkResume, 15000);
|
312
|
+
});
|
313
|
+
|
314
|
+
this.bind('ready', function(){
|
315
|
+
if(state.offline) {
|
316
|
+
state.offline = false;
|
317
|
+
clearInterval(state.resume);
|
318
|
+
state.resume = window.setInterval(checkResume, 1000);
|
319
|
+
}
|
320
|
+
|
321
|
+
if((!!config.auto_auth) && (!!config.system) && sysCallCount == 1 && authCount == 1) {
|
322
|
+
//
|
323
|
+
// Authenticate with the server
|
324
|
+
// Then we can safely reload the cache
|
325
|
+
// on cache success we accept the new key
|
326
|
+
//
|
327
|
+
jQuery.ajax('/tokens/new', {
|
328
|
+
type: 'GET',
|
329
|
+
dataType: 'text',
|
330
|
+
success: function(data, textStatus, jqXHR){
|
331
|
+
//
|
332
|
+
// Set the csrf token
|
333
|
+
// Get the new one-time-key
|
334
|
+
//
|
335
|
+
$('meta[name="csrf-token"]').attr('content', data);
|
336
|
+
|
337
|
+
jQuery.ajax('/tokens/authenticate', {
|
338
|
+
type: 'POST',
|
339
|
+
data: {
|
340
|
+
key: oneKey,
|
341
|
+
system: config.system
|
342
|
+
},
|
343
|
+
dataType: 'text',
|
344
|
+
success: function(data, textStatus, jqXHR){
|
345
|
+
// Accept the new key on success
|
346
|
+
jQuery.ajax('/tokens/accept', {
|
347
|
+
type: 'POST',
|
348
|
+
data: {
|
349
|
+
key: oneKey,
|
350
|
+
system: config.system
|
351
|
+
},
|
352
|
+
dataType: 'text',
|
353
|
+
success: function(data, textStatus, jqXHR){
|
354
|
+
//
|
355
|
+
// This can safely be ignored. Here for debugging
|
356
|
+
//
|
357
|
+
var yay = "success";
|
358
|
+
},
|
359
|
+
error: function(){
|
360
|
+
//
|
361
|
+
// This can safely be ignored. Here for debugging
|
362
|
+
//
|
363
|
+
var damn = "fail";
|
364
|
+
}
|
365
|
+
});
|
366
|
+
},
|
367
|
+
error: function(){
|
368
|
+
//
|
369
|
+
// This can safely be ignored. Here for debugging
|
370
|
+
//
|
371
|
+
var damn = "fail";
|
372
|
+
}
|
373
|
+
});
|
374
|
+
},
|
375
|
+
error: function(){
|
376
|
+
//
|
377
|
+
// This can safely be ignored. Here for debugging
|
378
|
+
//
|
379
|
+
var damn = "fail";
|
380
|
+
}
|
381
|
+
});
|
382
|
+
}
|
383
|
+
|
384
|
+
authCount = 0;
|
385
|
+
sysCallCount = 0;
|
386
|
+
});
|
387
|
+
|
388
|
+
//
|
389
|
+
// End Auto_auth ---------------
|
390
|
+
//
|
391
|
+
|
392
|
+
|
393
|
+
//
|
394
|
+
// Auto update functions
|
395
|
+
//
|
396
|
+
var appCache = window.applicationCache,
|
397
|
+
updateReady = false;
|
398
|
+
|
399
|
+
function bindCache(){
|
400
|
+
|
401
|
+
$(appCache).bind('updateready', function(){
|
402
|
+
appCache.swapCache(); // Swap cache has called key
|
403
|
+
|
404
|
+
if(!!config.forced_update)
|
405
|
+
window.location.reload();
|
406
|
+
else {
|
407
|
+
appCache = window.applicationCache;
|
408
|
+
bindCache();
|
409
|
+
updateReady = true;
|
410
|
+
}
|
411
|
+
});
|
412
|
+
|
413
|
+
}
|
414
|
+
|
415
|
+
if((!!config.idle_update) || (!!config.forced_update)) {
|
416
|
+
bindCache();
|
417
|
+
|
418
|
+
state.updater = setInterval('window.applicationCache.update();', 600000);
|
419
|
+
}
|
420
|
+
|
421
|
+
//
|
422
|
+
// Disconnects and removes the self reference to the object
|
423
|
+
// Once all external references are removed it will be garbage collected
|
424
|
+
//
|
425
|
+
this.destroy = function(){
|
426
|
+
clearInterval(state.resume);
|
427
|
+
clearInterval(state.updater);
|
428
|
+
if(state.connection != null)
|
429
|
+
state.connection.close();
|
430
|
+
var i;
|
431
|
+
for(i = 0; i < AutomateEm.Controllers.length; i = i + 1) {
|
432
|
+
if(AutomateEm.Controllers[i] == this) {
|
433
|
+
AutomateEm.Controllers.splice(i, 1);
|
434
|
+
break;
|
435
|
+
}
|
436
|
+
}
|
437
|
+
};
|
438
|
+
}
|
439
|
+
};
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
class TokensController < ActionController::Base
|
4
|
+
|
5
|
+
protect_from_forgery
|
6
|
+
before_filter :auth_user, :only => [:accept]
|
7
|
+
layout nil
|
8
|
+
|
9
|
+
|
10
|
+
def authenticate # Allowed through by application controller
|
11
|
+
#
|
12
|
+
# Auth(gen)
|
13
|
+
# check the system matches (set user and system in session)
|
14
|
+
# respond with success
|
15
|
+
#
|
16
|
+
dev = TrustedDevice.try_to_login(params[:key], true) # true means gen the next key
|
17
|
+
if params[:system].present? && dev.present? && params[:system].to_i == dev.control_system_id
|
18
|
+
session[:token] = dev.user_id
|
19
|
+
session[:system] = dev.control_system_id
|
20
|
+
session[:key] = params[:key]
|
21
|
+
cookies.permanent[:next_key] = {:value => dev.next_key, :path => URI.parse(request.referer).path}
|
22
|
+
|
23
|
+
render :nothing => true # success!
|
24
|
+
else
|
25
|
+
render :nothing => true, :status => :forbidden # 403
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def accept
|
31
|
+
dev = TrustedDevice.where('user_id = ? AND control_system_id = ? AND one_time_key = ? AND (expires IS NULL OR expires > ?)',
|
32
|
+
session[:token], session[:system], session[:key], Time.now).first
|
33
|
+
|
34
|
+
if dev.present?
|
35
|
+
dev.accept_key
|
36
|
+
render :nothing => true # success!
|
37
|
+
else
|
38
|
+
render :nothing => true, :status => :forbidden # 403
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
#
|
44
|
+
# Build a new session for the interface if the existing one has expired
|
45
|
+
# This maintains the csrf security
|
46
|
+
# We don't want to reset the session if a valid user is already authenticated either
|
47
|
+
#
|
48
|
+
def new
|
49
|
+
reset_session unless session[:user].present?
|
50
|
+
|
51
|
+
render :text => form_authenticity_token
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def create
|
56
|
+
#
|
57
|
+
# Application controller ensures we are logged in as real user
|
58
|
+
# Ensure the user can access the control system requested (the control system does this too)
|
59
|
+
# Generate key, populate the session
|
60
|
+
#
|
61
|
+
user = session[:user].present? ? User.find(session[:user]) : nil # We have to be authed to get here
|
62
|
+
sys = user.control_systems.where('control_systems.id = ?', params[:system]).first unless user.nil?
|
63
|
+
if user.present? && sys.present?
|
64
|
+
|
65
|
+
dev = TrustedDevice.new
|
66
|
+
dev.reason = params[:trusted_device][:reason]
|
67
|
+
dev.user = user
|
68
|
+
dev.control_system = sys
|
69
|
+
dev.save
|
70
|
+
|
71
|
+
if !dev.new_record?
|
72
|
+
cookies.permanent[:next_key] = {:value => dev.one_time_key, :path => URI.parse(request.referer).path}
|
73
|
+
render :json => {} # success!
|
74
|
+
else
|
75
|
+
render :json => dev.errors.messages, :status => :not_acceptable # 406
|
76
|
+
end
|
77
|
+
else
|
78
|
+
if user.present?
|
79
|
+
render :json => {:control => 'could not find the system selected'}, :status => :forbidden # 403
|
80
|
+
else
|
81
|
+
render :json => {:you => 'are not authorised'}, :status => :forbidden # 403
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def servers
|
88
|
+
render :json => Server.all
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
|
95
|
+
def auth_user
|
96
|
+
redirect_to root_path unless session[:user].present? || session[:token].present?
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
data/app/models/setting.rb
CHANGED
@@ -19,7 +19,7 @@ class Setting < ActiveRecord::Base
|
|
19
19
|
if self[:text_value].blank?
|
20
20
|
self[:text_value] = ""
|
21
21
|
else
|
22
|
-
self[:text_value] = Encryptor.decrypt(Base64.decode64(self[:text_value]), {:key =>
|
22
|
+
self[:text_value] = Encryptor.decrypt(Base64.decode64(self[:text_value]), {:key => Rails.application.config.automate.encrypt_key, :algorithm => 'aes-256-cbc'})
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -29,7 +29,7 @@ class Setting < ActiveRecord::Base
|
|
29
29
|
if self[:text_value].blank?
|
30
30
|
self[:text_value] = ""
|
31
31
|
else
|
32
|
-
self[:text_value] = Base64.encode64(Encryptor.encrypt(self[:text_value], {:key =>
|
32
|
+
self[:text_value] = Base64.encode64(Encryptor.encrypt(self[:text_value], {:key => Rails.application.config.automate.encrypt_key, :algorithm => 'aes-256-cbc'}))
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
data/config/routes.rb
ADDED
@@ -14,20 +14,21 @@ module AutomateEm
|
|
14
14
|
@@load_lock.mon_synchronize {
|
15
15
|
begin
|
16
16
|
found = false
|
17
|
+
file = "#{dep.classname.underscore}.rb"
|
17
18
|
|
18
19
|
Rails.configuration.automate.module_paths.each do |path|
|
19
|
-
if File.exists?("#{path}/#{
|
20
|
-
load "#{path}/#{
|
20
|
+
if File.exists?("#{path}/#{file}")
|
21
|
+
load "#{path}/#{file}"
|
21
22
|
found = true
|
22
23
|
break
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
27
|
if not found
|
27
|
-
raise "File not found!"
|
28
|
+
raise "File not found! (#{file})"
|
28
29
|
end
|
29
30
|
|
30
|
-
@@modules[dep.id] = dep.classname.
|
31
|
+
@@modules[dep.id] = dep.classname.constantize
|
31
32
|
rescue => e
|
32
33
|
AutomateEm.print_error(System.logger, e, {
|
33
34
|
:message => "device module #{dep.actual_name} error whilst loading",
|
@@ -116,12 +117,15 @@ module AutomateEm
|
|
116
117
|
#
|
117
118
|
# Instance of a user module
|
118
119
|
#
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
120
|
+
begin
|
121
|
+
@instance = Modules[controllerDevice.dependency_id].new(controllerDevice.tls, controllerDevice.makebreak)
|
122
|
+
@instance.join_system(@system)
|
123
|
+
@@instances[@device] = @instance
|
124
|
+
@@devices[baselookup] = @instance
|
125
|
+
@@lookup[@instance] = [@device]
|
126
|
+
ensure
|
127
|
+
@@lookup_lock.unlock #UNLOCK!! so we can lookup settings in on_load
|
128
|
+
end
|
125
129
|
|
126
130
|
devBase = nil
|
127
131
|
|
@@ -179,13 +183,16 @@ module AutomateEm
|
|
179
183
|
#
|
180
184
|
# add parent may lock at this point!
|
181
185
|
#
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
186
|
+
begin
|
187
|
+
@instance = @@devices[baselookup]
|
188
|
+
@@lookup[@instance] << @device
|
189
|
+
@@instances[@device] = @instance
|
190
|
+
EM.defer do
|
191
|
+
@instance.join_system(@system)
|
192
|
+
end
|
193
|
+
ensure
|
194
|
+
@@lookup_lock.unlock #UNLOCK!!
|
187
195
|
end
|
188
|
-
@@lookup_lock.unlock #UNLOCK!!
|
189
196
|
end
|
190
197
|
end
|
191
198
|
end
|
@@ -190,7 +190,7 @@ module AutomateEm
|
|
190
190
|
if !@controller.active || force
|
191
191
|
if @logger.nil?
|
192
192
|
if Rails.env.production?
|
193
|
-
@logger = Logger.new("
|
193
|
+
@logger = Logger.new(Rails.root.join("log/system_#{@controller.id}.log").to_s, 10, 4194304)
|
194
194
|
else
|
195
195
|
@logger = Logger.new(STDOUT)
|
196
196
|
end
|
data/lib/automate-em/engine.rb
CHANGED
data/lib/automate-em/version.rb
CHANGED
@@ -12,12 +12,12 @@ class ModuleGenerator < Rails::Generators::NamedBase
|
|
12
12
|
scope = []
|
13
13
|
text = ""
|
14
14
|
param.map! {|item|
|
15
|
-
item = item.
|
15
|
+
item = item.camelcase
|
16
16
|
scope << item
|
17
17
|
text += "module #{scope.join('::')}; end\n"
|
18
18
|
item
|
19
19
|
}
|
20
|
-
param << name.
|
20
|
+
param << name.camelcase
|
21
21
|
scope = param.join('::')
|
22
22
|
|
23
23
|
|
@@ -27,7 +27,7 @@ class ModuleGenerator < Rails::Generators::NamedBase
|
|
27
27
|
text += <<-FILE
|
28
28
|
|
29
29
|
|
30
|
-
class #{scope} < AutomateEm::#{type.downcase.
|
30
|
+
class #{scope} < AutomateEm::#{type.downcase.camelcase}
|
31
31
|
def on_load
|
32
32
|
end
|
33
33
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: automate-em
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -194,6 +194,8 @@ executables: []
|
|
194
194
|
extensions: []
|
195
195
|
extra_rdoc_files: []
|
196
196
|
files:
|
197
|
+
- app/assets/javascripts/jquery.automate.js
|
198
|
+
- app/controllers/tokens_controller.rb
|
197
199
|
- app/models/controller_device.rb
|
198
200
|
- app/models/controller_http_service.rb
|
199
201
|
- app/models/controller_logic.rb
|
@@ -205,6 +207,7 @@ files:
|
|
205
207
|
- app/models/trusted_device.rb
|
206
208
|
- app/models/user_zone.rb
|
207
209
|
- app/models/zone.rb
|
210
|
+
- config/routes.rb
|
208
211
|
- db/migrate/20111001022500_init.rb
|
209
212
|
- db/migrate/20111017213801_one_time_key.rb
|
210
213
|
- db/migrate/20111021071632_encrypt_setting.rb
|
@@ -268,8 +271,10 @@ files:
|
|
268
271
|
- test/dummy/Rakefile
|
269
272
|
- test/dummy/README.rdoc
|
270
273
|
- test/dummy/script/rails
|
274
|
+
- test/functional/tokens_controller_test.rb
|
271
275
|
- test/integration/navigation_test.rb
|
272
276
|
- test/test_helper.rb
|
277
|
+
- test/unit/helpers/tokens_helper_test.rb
|
273
278
|
homepage: http://advancedcontrol.com.au/
|
274
279
|
licenses: []
|
275
280
|
post_install_message:
|
@@ -324,5 +329,7 @@ test_files:
|
|
324
329
|
- test/dummy/Rakefile
|
325
330
|
- test/dummy/README.rdoc
|
326
331
|
- test/dummy/script/rails
|
332
|
+
- test/functional/tokens_controller_test.rb
|
327
333
|
- test/integration/navigation_test.rb
|
328
334
|
- test/test_helper.rb
|
335
|
+
- test/unit/helpers/tokens_helper_test.rb
|