rhoconnect 3.0.0.beta1

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.
Files changed (361) hide show
  1. data/CHANGELOG +208 -0
  2. data/CREDITS +38 -0
  3. data/Gemfile +18 -0
  4. data/Gemfile.lock +97 -0
  5. data/LICENSE +75 -0
  6. data/README.md +10 -0
  7. data/Rakefile +82 -0
  8. data/bench/bench +7 -0
  9. data/bench/bench_runner.rb +112 -0
  10. data/bench/benchapp/Gemfile +21 -0
  11. data/bench/benchapp/Gemfile.lock +76 -0
  12. data/bench/benchapp/Rakefile +22 -0
  13. data/bench/benchapp/application.rb +39 -0
  14. data/bench/benchapp/config.ru +36 -0
  15. data/bench/benchapp/settings/license.key +1 -0
  16. data/bench/benchapp/settings/settings.yml +20 -0
  17. data/bench/benchapp/sources/mock_adapter.rb +55 -0
  18. data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
  19. data/bench/benchapp/spec/sources/mock_adapter_spec.rb +25 -0
  20. data/bench/benchapp/spec/sources/queue_mock_adapter_spec.rb +25 -0
  21. data/bench/benchapp/spec/spec_helper.rb +42 -0
  22. data/bench/blobapp/Gemfile +31 -0
  23. data/bench/blobapp/Gemfile.lock +103 -0
  24. data/bench/blobapp/Rakefile +25 -0
  25. data/bench/blobapp/application.rb +44 -0
  26. data/bench/blobapp/config.ru +36 -0
  27. data/bench/blobapp/settings/license.key +1 -0
  28. data/bench/blobapp/settings/settings.yml +16 -0
  29. data/bench/blobapp/sources/blob_adapter.rb +71 -0
  30. data/bench/blobapp/spec/sources/blob_adapter_spec.rb +25 -0
  31. data/bench/blobapp/spec/spec_helper.rb +42 -0
  32. data/bench/lib/bench/cli.rb +16 -0
  33. data/bench/lib/bench/logging.rb +13 -0
  34. data/bench/lib/bench/mock_client.rb +41 -0
  35. data/bench/lib/bench/result.rb +50 -0
  36. data/bench/lib/bench/runner.rb +107 -0
  37. data/bench/lib/bench/session.rb +67 -0
  38. data/bench/lib/bench/statistics.rb +56 -0
  39. data/bench/lib/bench/test_data.rb +98 -0
  40. data/bench/lib/bench/timer.rb +10 -0
  41. data/bench/lib/bench/utils.rb +49 -0
  42. data/bench/lib/bench.rb +129 -0
  43. data/bench/lib/testdata/100-data.txt +148 -0
  44. data/bench/lib/testdata/5-data.txt +9 -0
  45. data/bench/lib/testdata/images/icon.ico +0 -0
  46. data/bench/lib/testdata/images/icon.png +0 -0
  47. data/bench/lib/testdata/images/loading-Landscape.png +0 -0
  48. data/bench/lib/testdata/images/loading-LandscapeLeft.png +0 -0
  49. data/bench/lib/testdata/images/loading-LandscapeRight.png +0 -0
  50. data/bench/lib/testdata/images/loading-Portrait.png +0 -0
  51. data/bench/lib/testdata/images/loading-PortraitUpsideDown.png +0 -0
  52. data/bench/lib/testdata/images/loading.png +0 -0
  53. data/bench/lib/testdata/images/loading@2x.png +0 -0
  54. data/bench/run_bench.sh +42 -0
  55. data/bench/run_blob_script.sh +3 -0
  56. data/bench/run_cud_script.sh +3 -0
  57. data/bench/run_query_md_script.sh +3 -0
  58. data/bench/run_query_only_script.sh +3 -0
  59. data/bench/run_query_script.sh +3 -0
  60. data/bench/scripts/blob_cud_script.rb +98 -0
  61. data/bench/scripts/cud_script.rb +92 -0
  62. data/bench/scripts/helpers.rb +101 -0
  63. data/bench/scripts/query_md_script.rb +45 -0
  64. data/bench/scripts/query_only_script.rb +51 -0
  65. data/bench/scripts/query_script.rb +45 -0
  66. data/bench/spec/bench_spec_helper.rb +33 -0
  67. data/bench/spec/logging_spec.rb +15 -0
  68. data/bench/spec/mock_adapter_spec.rb +61 -0
  69. data/bench/spec/mock_client_spec.rb +65 -0
  70. data/bench/spec/result_spec.rb +61 -0
  71. data/bench/spec/utils_spec.rb +36 -0
  72. data/bin/rhoconnect +34 -0
  73. data/bin/rhoconnect-setup +84 -0
  74. data/doc/async-jobs.txt +69 -0
  75. data/doc/authentication.txt +76 -0
  76. data/doc/benchmarks.txt +168 -0
  77. data/doc/blob-sync.txt +130 -0
  78. data/doc/bulk-sync.txt +102 -0
  79. data/doc/client.txt +432 -0
  80. data/doc/command-line.txt +210 -0
  81. data/doc/contributing.txt +60 -0
  82. data/doc/deploying.txt +82 -0
  83. data/doc/install.txt +28 -0
  84. data/doc/introduction.txt +20 -0
  85. data/doc/licensing.txt +18 -0
  86. data/doc/metadata.txt +458 -0
  87. data/doc/migration.txt +182 -0
  88. data/doc/public/css/print.css +29 -0
  89. data/doc/public/css/screen.css +257 -0
  90. data/doc/public/css/style.css +20 -0
  91. data/doc/push.txt +135 -0
  92. data/doc/release.txt +41 -0
  93. data/doc/rest-api.txt +367 -0
  94. data/doc/source-adapters.txt +325 -0
  95. data/doc/stats-middleware.txt +69 -0
  96. data/doc/testing.txt +222 -0
  97. data/doc/tutorial.txt +315 -0
  98. data/doc/web-console.txt +35 -0
  99. data/examples/simple/Rakefile +14 -0
  100. data/examples/simple/application.rb +27 -0
  101. data/examples/simple/config.ru +49 -0
  102. data/examples/simple/settings/license.key +1 -0
  103. data/examples/simple/settings/settings.yml +23 -0
  104. data/examples/simple/sources/sample_adapter.rb +5 -0
  105. data/examples/simple/sources/simple_adapter.rb +5 -0
  106. data/generators/rhoconnect.rb +119 -0
  107. data/generators/templates/application/Gemfile +21 -0
  108. data/generators/templates/application/Rakefile +22 -0
  109. data/generators/templates/application/application.rb +39 -0
  110. data/generators/templates/application/config.ru +36 -0
  111. data/generators/templates/application/settings/license.key +1 -0
  112. data/generators/templates/application/settings/settings.yml +14 -0
  113. data/generators/templates/application/spec/spec_helper.rb +42 -0
  114. data/generators/templates/source/source_adapter.rb +47 -0
  115. data/generators/templates/source/source_spec.rb +25 -0
  116. data/install.sh +408 -0
  117. data/installer/unix-like/rho_connect_install_checkers.rb +140 -0
  118. data/installer/unix-like/rho_connect_install_constants.rb +51 -0
  119. data/installer/unix-like/rho_connect_install_debian.rb +63 -0
  120. data/installer/unix-like/rho_connect_install_dnd.rb +58 -0
  121. data/installer/unix-like/rho_connect_install_get_params.rb +30 -0
  122. data/installer/unix-like/rho_connect_install_installers.rb +142 -0
  123. data/installer/unix-like/rho_connect_install_utilities.rb +85 -0
  124. data/installer/unix-like/rho_connect_install_yum.rb +63 -0
  125. data/installer/unix-like/rhoinstaller.rb +89 -0
  126. data/installer/utils/create_texts.rb +366 -0
  127. data/installer/utils/install_test.rb +140 -0
  128. data/installer/windows/EnvVarUpdate.nsh +328 -0
  129. data/installer/windows/ServiceLib.nsh +369 -0
  130. data/installer/windows/configUi.ini +44 -0
  131. data/installer/windows/icon.ico +0 -0
  132. data/installer/windows/rhosync.nsi +418 -0
  133. data/installer/windows/uninstall.bat +7 -0
  134. data/lib/rhoconnect/api/admin/get_api_token.rb +14 -0
  135. data/lib/rhoconnect/api/admin/get_license_info.rb +8 -0
  136. data/lib/rhoconnect/api/admin/login.rb +6 -0
  137. data/lib/rhoconnect/api/admin/reset.rb +10 -0
  138. data/lib/rhoconnect/api/admin/stats.rb +21 -0
  139. data/lib/rhoconnect/api/application/bulk_data.rb +7 -0
  140. data/lib/rhoconnect/api/application/clientcreate.rb +8 -0
  141. data/lib/rhoconnect/api/application/clientlogin.rb +6 -0
  142. data/lib/rhoconnect/api/application/clientregister.rb +6 -0
  143. data/lib/rhoconnect/api/application/clientreset.rb +6 -0
  144. data/lib/rhoconnect/api/application/query.rb +7 -0
  145. data/lib/rhoconnect/api/application/queue_updates.rb +6 -0
  146. data/lib/rhoconnect/api/application/search.rb +6 -0
  147. data/lib/rhoconnect/api/client/create_client.rb +3 -0
  148. data/lib/rhoconnect/api/client/delete_client.rb +5 -0
  149. data/lib/rhoconnect/api/client/get_client_params.rb +3 -0
  150. data/lib/rhoconnect/api/client/list_client_docs.rb +12 -0
  151. data/lib/rhoconnect/api/client/list_clients.rb +3 -0
  152. data/lib/rhoconnect/api/client/ping.rb +7 -0
  153. data/lib/rhoconnect/api/source/get_adapter.rb +3 -0
  154. data/lib/rhoconnect/api/source/get_db_doc.rb +7 -0
  155. data/lib/rhoconnect/api/source/get_source_params.rb +3 -0
  156. data/lib/rhoconnect/api/source/list_source_docs.rb +10 -0
  157. data/lib/rhoconnect/api/source/list_sources.rb +15 -0
  158. data/lib/rhoconnect/api/source/push_deletes.rb +8 -0
  159. data/lib/rhoconnect/api/source/push_objects.rb +8 -0
  160. data/lib/rhoconnect/api/source/save_adapter.rb +3 -0
  161. data/lib/rhoconnect/api/source/set_db_doc.rb +8 -0
  162. data/lib/rhoconnect/api/source/set_refresh_time.rb +8 -0
  163. data/lib/rhoconnect/api/source/upload_file.rb +4 -0
  164. data/lib/rhoconnect/api/user/create_user.rb +7 -0
  165. data/lib/rhoconnect/api/user/delete_user.rb +9 -0
  166. data/lib/rhoconnect/api/user/list_users.rb +3 -0
  167. data/lib/rhoconnect/api/user/update_user.rb +4 -0
  168. data/lib/rhoconnect/api_token.rb +19 -0
  169. data/lib/rhoconnect/app.rb +76 -0
  170. data/lib/rhoconnect/bulk_data/bulk_data.rb +88 -0
  171. data/lib/rhoconnect/bulk_data/syncdb.index.schema +4 -0
  172. data/lib/rhoconnect/bulk_data/syncdb.schema +41 -0
  173. data/lib/rhoconnect/bulk_data.rb +2 -0
  174. data/lib/rhoconnect/client.rb +96 -0
  175. data/lib/rhoconnect/client_sync.rb +412 -0
  176. data/lib/rhoconnect/console/app/helpers/auth_helper.rb +22 -0
  177. data/lib/rhoconnect/console/app/helpers/extensions.rb +19 -0
  178. data/lib/rhoconnect/console/app/helpers/helpers.rb +57 -0
  179. data/lib/rhoconnect/console/app/public/ThickBox.css +649 -0
  180. data/lib/rhoconnect/console/app/public/home.css +438 -0
  181. data/lib/rhoconnect/console/app/public/images/foot_logo_rhoconnect.png +0 -0
  182. data/lib/rhoconnect/console/app/public/images/header_halo.jpg +0 -0
  183. data/lib/rhoconnect/console/app/public/images/land_separator.gif +0 -0
  184. data/lib/rhoconnect/console/app/public/images/landing_header.jpg +0 -0
  185. data/lib/rhoconnect/console/app/public/images/logo_rhoconnect.png +0 -0
  186. data/lib/rhoconnect/console/app/public/images/rhomobile_rhohub_logo.png +0 -0
  187. data/lib/rhoconnect/console/app/public/images/tabs_separator.png +0 -0
  188. data/lib/rhoconnect/console/app/public/jqplot/excanvas.min.js +35 -0
  189. data/lib/rhoconnect/console/app/public/jqplot/jqplot.barRenderer.min.js +34 -0
  190. data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasAxisLabelRenderer.js +187 -0
  191. data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasAxisTickRenderer.js +226 -0
  192. data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasTextRenderer.js +408 -0
  193. data/lib/rhoconnect/console/app/public/jqplot/jqplot.categoryAxisRenderer.min.js +34 -0
  194. data/lib/rhoconnect/console/app/public/jqplot/jqplot.cursor.js +952 -0
  195. data/lib/rhoconnect/console/app/public/jqplot/jqplot.dateAxisRenderer.js +313 -0
  196. data/lib/rhoconnect/console/app/public/jqplot/jqplot.dateAxisRenderer.min.js +34 -0
  197. data/lib/rhoconnect/console/app/public/jqplot/jqplot.pointLabels.min.js +34 -0
  198. data/lib/rhoconnect/console/app/public/jqplot/jquery-1.4.2.min.js +154 -0
  199. data/lib/rhoconnect/console/app/public/jqplot/jquery.jqplot.min.css +1 -0
  200. data/lib/rhoconnect/console/app/public/jqplot/jquery.jqplot.min.js +34 -0
  201. data/lib/rhoconnect/console/app/public/main.css +7 -0
  202. data/lib/rhoconnect/console/app/public/reset.css +76 -0
  203. data/lib/rhoconnect/console/app/public/style.css +2201 -0
  204. data/lib/rhoconnect/console/app/public/text.txt +0 -0
  205. data/lib/rhoconnect/console/app/routes/adapter.rb +28 -0
  206. data/lib/rhoconnect/console/app/routes/auth.rb +29 -0
  207. data/lib/rhoconnect/console/app/routes/client.rb +31 -0
  208. data/lib/rhoconnect/console/app/routes/docs.rb +145 -0
  209. data/lib/rhoconnect/console/app/routes/heroku.rb +19 -0
  210. data/lib/rhoconnect/console/app/routes/home.rb +63 -0
  211. data/lib/rhoconnect/console/app/routes/timing.rb +242 -0
  212. data/lib/rhoconnect/console/app/routes/user.rb +117 -0
  213. data/lib/rhoconnect/console/app/views/adapter.erb +16 -0
  214. data/lib/rhoconnect/console/app/views/client.erb +30 -0
  215. data/lib/rhoconnect/console/app/views/content.erb +14 -0
  216. data/lib/rhoconnect/console/app/views/doc.erb +8 -0
  217. data/lib/rhoconnect/console/app/views/docdata.erb +28 -0
  218. data/lib/rhoconnect/console/app/views/docs.erb +30 -0
  219. data/lib/rhoconnect/console/app/views/edituser.erb +13 -0
  220. data/lib/rhoconnect/console/app/views/headermenu.erb +40 -0
  221. data/lib/rhoconnect/console/app/views/home.erb +24 -0
  222. data/lib/rhoconnect/console/app/views/index.erb +58 -0
  223. data/lib/rhoconnect/console/app/views/jqplot.erb +52 -0
  224. data/lib/rhoconnect/console/app/views/layout.erb +165 -0
  225. data/lib/rhoconnect/console/app/views/login.erb +26 -0
  226. data/lib/rhoconnect/console/app/views/newuser.erb +17 -0
  227. data/lib/rhoconnect/console/app/views/ping.erb +28 -0
  228. data/lib/rhoconnect/console/app/views/result.erb +11 -0
  229. data/lib/rhoconnect/console/app/views/rightboxlinks.erb +15 -0
  230. data/lib/rhoconnect/console/app/views/select_doc.erb +17 -0
  231. data/lib/rhoconnect/console/app/views/upload_doc.erb +23 -0
  232. data/lib/rhoconnect/console/app/views/user.erb +29 -0
  233. data/lib/rhoconnect/console/app/views/users.erb +12 -0
  234. data/lib/rhoconnect/console/rhoconnect_api.rb +245 -0
  235. data/lib/rhoconnect/console/server.rb +32 -0
  236. data/lib/rhoconnect/console.rb +3 -0
  237. data/lib/rhoconnect/cors.rb +229 -0
  238. data/lib/rhoconnect/credential.rb +9 -0
  239. data/lib/rhoconnect/db_adapter.rb +46 -0
  240. data/lib/rhoconnect/document.rb +49 -0
  241. data/lib/rhoconnect/dynamic_adapter.rb +91 -0
  242. data/lib/rhoconnect/generator.rb +1 -0
  243. data/lib/rhoconnect/jobs/bulk_data_job.rb +203 -0
  244. data/lib/rhoconnect/jobs/ping_job.rb +46 -0
  245. data/lib/rhoconnect/jobs/source_job.rb +16 -0
  246. data/lib/rhoconnect/license.rb +86 -0
  247. data/lib/rhoconnect/lock_ops.rb +11 -0
  248. data/lib/rhoconnect/model.rb +414 -0
  249. data/lib/rhoconnect/ping/android.rb +56 -0
  250. data/lib/rhoconnect/ping/apple.rb +52 -0
  251. data/lib/rhoconnect/ping/blackberry.rb +56 -0
  252. data/lib/rhoconnect/ping.rb +3 -0
  253. data/lib/rhoconnect/read_state.rb +31 -0
  254. data/lib/rhoconnect/rho_indifferent_access.rb +88 -0
  255. data/lib/rhoconnect/server/views/index.erb +13 -0
  256. data/lib/rhoconnect/server.rb +286 -0
  257. data/lib/rhoconnect/source.rb +289 -0
  258. data/lib/rhoconnect/source_adapter.rb +123 -0
  259. data/lib/rhoconnect/source_sync.rb +302 -0
  260. data/lib/rhoconnect/stats/middleware.rb +20 -0
  261. data/lib/rhoconnect/stats/record.rb +108 -0
  262. data/lib/rhoconnect/store.rb +232 -0
  263. data/lib/rhoconnect/tasks.rb +350 -0
  264. data/lib/rhoconnect/test_methods.rb +220 -0
  265. data/lib/rhoconnect/user.rb +95 -0
  266. data/lib/rhoconnect/version.rb +3 -0
  267. data/lib/rhoconnect/x_domain_session_wrapper.rb +53 -0
  268. data/lib/rhoconnect.rb +285 -0
  269. data/rhoconnect.gemspec +67 -0
  270. data/spec/api/admin/api_token_spec.rb +14 -0
  271. data/spec/api/admin/get_api_token_spec.rb +36 -0
  272. data/spec/api/admin/get_license_info_spec.rb +38 -0
  273. data/spec/api/admin/reset_spec.rb +22 -0
  274. data/spec/api/admin/stats_spec.rb +66 -0
  275. data/spec/api/api_helper.rb +21 -0
  276. data/spec/api/application/rhoconnect_api_spec.rb +548 -0
  277. data/spec/api/client/create_client_spec.rb +13 -0
  278. data/spec/api/client/delete_client_spec.rb +13 -0
  279. data/spec/api/client/get_client_params_spec.rb +18 -0
  280. data/spec/api/client/list_client_docs_spec.rb +32 -0
  281. data/spec/api/client/list_clients_spec.rb +22 -0
  282. data/spec/api/client/ping_spec.rb +23 -0
  283. data/spec/api/rhosync_api_spec.rb.orig +606 -0
  284. data/spec/api/source/adapter_spec.rb +29 -0
  285. data/spec/api/source/get_db_doc_spec.rb +21 -0
  286. data/spec/api/source/get_source_params_spec.rb +32 -0
  287. data/spec/api/source/list_source_docs_spec.rb +25 -0
  288. data/spec/api/source/list_sources_spec.rb +26 -0
  289. data/spec/api/source/push_deletes_spec.rb +18 -0
  290. data/spec/api/source/push_objects_spec.rb +27 -0
  291. data/spec/api/source/set_db_doc_spec.rb +19 -0
  292. data/spec/api/source/set_refresh_time_spec.rb +43 -0
  293. data/spec/api/source/upload_file_spec.rb +26 -0
  294. data/spec/api/user/create_user_spec.rb +16 -0
  295. data/spec/api/user/delete_user_spec.rb +36 -0
  296. data/spec/api/user/list_users_spec.rb +30 -0
  297. data/spec/api/user/update_user_spec.rb +31 -0
  298. data/spec/api_token_spec.rb +14 -0
  299. data/spec/app_spec.rb +18 -0
  300. data/spec/apps/emptyapp/application.rb +27 -0
  301. data/spec/apps/emptyapp/settings/license.key +1 -0
  302. data/spec/apps/emptyapp/settings/settings.yml +14 -0
  303. data/spec/apps/rhotestapp/Rakefile +1 -0
  304. data/spec/apps/rhotestapp/application.rb +19 -0
  305. data/spec/apps/rhotestapp/config.ru +1 -0
  306. data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
  307. data/spec/apps/rhotestapp/settings/license.key +1 -0
  308. data/spec/apps/rhotestapp/settings/settings.yml +36 -0
  309. data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
  310. data/spec/apps/rhotestapp/sources/fixed_schema_adapter.rb +28 -0
  311. data/spec/apps/rhotestapp/sources/sample_adapter.rb +71 -0
  312. data/spec/apps/rhotestapp/sources/simple_adapter.rb +41 -0
  313. data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
  314. data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
  315. data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
  316. data/spec/bulk_data/bulk_data_spec.rb +97 -0
  317. data/spec/client_spec.rb +124 -0
  318. data/spec/client_sync_spec.rb +774 -0
  319. data/spec/doc/base.html +72 -0
  320. data/spec/doc/doc_spec.rb +376 -0
  321. data/spec/doc/footer.html +4 -0
  322. data/spec/doc/header.html +30 -0
  323. data/spec/document_spec.rb +31 -0
  324. data/spec/dynamic_adapter_spec.rb +43 -0
  325. data/spec/factories/factories.rb +17 -0
  326. data/spec/generator/generator_spec.rb +58 -0
  327. data/spec/generator/generator_spec_helper.rb +9 -0
  328. data/spec/jobs/bulk_data_job_spec.rb +125 -0
  329. data/spec/jobs/ping_job_spec.rb +102 -0
  330. data/spec/jobs/source_job_spec.rb +29 -0
  331. data/spec/license_spec.rb +66 -0
  332. data/spec/model_spec.rb +273 -0
  333. data/spec/perf/bulk_data_perf_spec.rb +32 -0
  334. data/spec/perf/perf_spec_helper.rb +50 -0
  335. data/spec/perf/store_perf_spec.rb +27 -0
  336. data/spec/ping/android_spec.rb +91 -0
  337. data/spec/ping/apple_spec.rb +70 -0
  338. data/spec/ping/blackberry_spec.rb +62 -0
  339. data/spec/read_state_spec.rb +35 -0
  340. data/spec/rhosync_spec.rb +75 -0
  341. data/spec/server/cors_spec.rb +287 -0
  342. data/spec/server/server_spec.rb +470 -0
  343. data/spec/server/x_domain_session_wrapper_spec.rb +150 -0
  344. data/spec/source_adapter_spec.rb +125 -0
  345. data/spec/source_spec.rb +114 -0
  346. data/spec/source_sync_spec.rb +328 -0
  347. data/spec/spec.opts +4 -0
  348. data/spec/spec_helper.rb +231 -0
  349. data/spec/stats/middleware_spec.rb +53 -0
  350. data/spec/stats/record_spec.rb +92 -0
  351. data/spec/store_spec.rb +251 -0
  352. data/spec/support/shared_examples.rb +168 -0
  353. data/spec/sync_states_spec.rb +72 -0
  354. data/spec/test_methods_spec.rb +134 -0
  355. data/spec/testdata/1000-data.txt +1414 -0
  356. data/spec/testdata/compressed/compress-data.txt +1 -0
  357. data/spec/testdata/upload1.txt +1 -0
  358. data/spec/testdata/upload2.txt +1 -0
  359. data/spec/user_spec.rb +139 -0
  360. data/tasks/redis.rake +206 -0
  361. metadata +706 -0
@@ -0,0 +1,350 @@
1
+ require 'json'
2
+ require 'zip/zip'
3
+ require 'uri'
4
+ require File.join(File.dirname(__FILE__),'console','rhoconnect_api')
5
+
6
+ module Rhoconnect
7
+ module TaskHelper
8
+ def post(path,params)
9
+ req = Net::HTTP.new($host,$port)
10
+ resp = req.post(path, params.to_json, 'Content-Type' => 'application/json')
11
+ print_resp(resp, resp.is_a?(Net::HTTPSuccess) ? true : false)
12
+ end
13
+
14
+ def print_resp(resp,success=true)
15
+ if success
16
+ puts "=> OK"
17
+ else
18
+ puts "=> FAILED"
19
+ end
20
+ puts "=> " + resp.body if resp and resp.body and resp.body.length > 0
21
+ end
22
+
23
+ def archive(path)
24
+ File.join(path,File.basename(path))+'.zip'
25
+ end
26
+
27
+ def ask(msg)
28
+ print msg
29
+ STDIN.gets.chomp
30
+ end
31
+
32
+ def load_settings(file)
33
+ begin
34
+ $settings = YAML.load_file(file)
35
+ rescue Exception => e
36
+ puts "Error opening settings file #{file}: #{e}."
37
+ puts e.backtrace.join("\n")
38
+ raise e
39
+ end
40
+ end
41
+
42
+ def rhoconnect_socket
43
+ "/tmp/rhoconnect.dtach"
44
+ end
45
+
46
+ def rhoconnect_pid
47
+ "/tmp/rhoconnect.pid"
48
+ end
49
+
50
+ def windows?
51
+ RUBY_PLATFORM =~ /(win|w)32$/
52
+ end
53
+
54
+ def ruby19?
55
+ RUBY_VERSION =~ /1.9/
56
+ end
57
+
58
+ def jruby?
59
+ defined?(JRUBY_VERSION)
60
+ end
61
+
62
+ def thin?
63
+ begin
64
+ require 'thin'
65
+ 'rackup -s thin'
66
+ rescue LoadError
67
+ nil
68
+ end
69
+ end
70
+
71
+ def mongrel?
72
+ begin
73
+ require 'mongrel'
74
+ 'rackup -s mongrel'
75
+ rescue LoadError
76
+ nil
77
+ end
78
+ end
79
+
80
+ def report_missing_server
81
+ msg =<<-EOF
82
+ Could not find 'thin' or 'mongrel' on your system. Please install one:
83
+ gem install thin
84
+ or
85
+ gem install mongrel
86
+ EOF
87
+ puts msg
88
+ exit 1
89
+ end
90
+
91
+ # def jetty_rackup?
92
+ # 'jruby -S jetty-rackup'
93
+ # end
94
+
95
+ def trinidad?
96
+ 'jruby -S trinidad -p 9292 -r config.ru'
97
+ end
98
+ end
99
+ end
100
+
101
+ namespace :rhoconnect do
102
+ include Rhoconnect::TaskHelper
103
+ include RhoconnectApi
104
+
105
+ task :config do
106
+ $settings = load_settings(File.join('settings','settings.yml'))
107
+ $env = (ENV['RHO_ENV'] || ENV['RACK_ENV'] || :development).to_sym
108
+ uri = URI.parse($settings[$env][:syncserver])
109
+ $url = "#{uri.scheme}://#{uri.host}"
110
+ $url = "#{$url}:#{uri.port}" if uri.port && uri.port != 80
111
+ $host = uri.host
112
+ $port = uri.port
113
+ $appname = $settings[$env][:syncserver].split('/').last
114
+ $token_file = File.join(ENV['HOME'],'.rhoconnect_token')
115
+ $token = File.read($token_file) if File.exist?($token_file)
116
+ end
117
+
118
+ task :dtach_installed do
119
+ if !windows? and (`which dtach` == '')
120
+ puts "WARNING: dtach not installed or not on path, some tasks will not work!"
121
+ puts " Install with '[sudo] rake dtach:install'"
122
+ exit
123
+ end
124
+ end
125
+
126
+ desc "Reset the rhoconnect database (you will need to run rhoconnect:get_token afterwards)"
127
+ task :reset => :config do
128
+ confirm = ask " Are you sure? Resetting will remove all data!\n It will also return an error code to all\n existing devices when they connect! (yes/no): "
129
+ if confirm == 'yes'
130
+ RhoconnectApi.reset($url,$token)
131
+ puts "Database reset."
132
+ else
133
+ puts "Cancelling."
134
+ end
135
+ end
136
+
137
+ desc "Fetches current api token from rhoconnect"
138
+ task :get_token => :config do
139
+ password = ''
140
+ login = ask "admin login: "
141
+ begin
142
+ system "stty -echo"
143
+ password = ask "\nadmin password: "
144
+ system "stty echo"
145
+ rescue NoMethodError, Interrupt
146
+ system "stty echo"
147
+ exit
148
+ end
149
+ puts ''
150
+ begin
151
+ $token = RhoconnectApi.get_token($url,login,password)
152
+ rescue
153
+ puts "Login failed."
154
+ exit
155
+ end
156
+ File.open($token_file,'w') {|f| f.write $token}
157
+ puts "Token is saved in: #{$token_file}"
158
+ end
159
+
160
+ desc "Clean rhoconnect, get token, and create new user"
161
+ task :clean_start => [:get_token, :reset, :get_token, :create_user]
162
+
163
+ desc "Alias for `rake rhoconnect:stop; rake rhoconnect:start`"
164
+ task :restart => [:stop, :start]
165
+
166
+ desc "Creates and subscribes user for application in rhoconnect"
167
+ task :create_user => :config do
168
+ password = ''
169
+ login = ask "new user login: "
170
+ begin
171
+ system "stty -echo"
172
+ password = ask "\nnew user password: "
173
+ system "stty echo"
174
+ rescue NoMethodError, Interrupt
175
+ system "stty echo"
176
+ exit
177
+ end
178
+ puts ''
179
+ RhoconnectApi.create_user($url,$token,login,password)
180
+ end
181
+
182
+ desc "Deletes a user from rhoconnect"
183
+ task :delete_user => :config do
184
+ login = ask "user to delete: "
185
+ RhoconnectApi.delete_user($url,$token,login)
186
+ end
187
+
188
+ desc "Deletes a device from rhoconnect"
189
+ task :delete_device => :config do
190
+ user_id = ask "device's user_id: "
191
+ device_id = ask "device to delete: "
192
+ RhoconnectApi.delete_client($url,$token,user_id,device_id)
193
+ end
194
+
195
+ desc "Sets the admin password"
196
+ task :set_admin_password => :get_token do
197
+ new_pass,new_pass_confirm = '',''
198
+ begin
199
+ system "stty -echo"
200
+ new_pass = ask "\nnew admin password: "
201
+ new_pass_confirm = ask "\nconfirm new admin password: "
202
+ system "stty echo"
203
+ rescue NoMethodError, Interrupt
204
+ system "stty echo"
205
+ exit
206
+ end
207
+ if new_pass == ''
208
+ puts "\nNew password can't be empty."
209
+ elsif new_pass == new_pass_confirm
210
+ puts ""
211
+ post("/api/update_user", {:app_name => $appname, :api_token => $token,
212
+ :attributes => {:new_password => new_pass}})
213
+ else
214
+ puts "\nNew password and confirmation must match."
215
+ end
216
+ end
217
+
218
+ desc "Reset source refresh time"
219
+ task :reset_refresh => :config do
220
+ user = ask "user: "
221
+ source_name = ask "source name: "
222
+ RestClient.post("#{$url}/api/set_refresh_time", {:api_token => $token,
223
+ :user_name => user, :source_name => source_name})
224
+ end
225
+
226
+ begin
227
+ require 'rspec/core/rake_task'
228
+ require 'rcov/rcovtask' unless (windows? || ruby19?)
229
+
230
+ desc "Run source adapter specs"
231
+ task :spec do
232
+ files = File.join('spec','**','*_spec.rb')
233
+ RSpec::Core::RakeTask.new('rhoconnect:spec') do |t|
234
+ t.pattern = FileList[files]
235
+ t.rspec_opts = %w(-fn -b --color)
236
+ unless (windows? || ruby19?)
237
+ t.rcov = true
238
+ t.rcov_opts = ['--exclude', 'spec/*,gems/*']
239
+ end
240
+ end
241
+ end
242
+ rescue LoadError
243
+ if windows?
244
+ puts "rspec not available. Install it with: "
245
+ puts "gem install rspec\n\n"
246
+ else
247
+ puts "rspec / rcov not available. Install it with: "
248
+ puts "gem install rspec rcov\n\n"
249
+ end
250
+ end
251
+
252
+ desc "Start rhoconnect server"
253
+ task :start => :dtach_installed do
254
+ cmd = (jruby?) ? trinidad? : (thin? || mongrel? || report_missing_server)
255
+ if windows?
256
+ puts 'Starting server in new window...'
257
+ system("start cmd.exe /c #{cmd} config.ru")
258
+ elsif jruby?
259
+ puts 'Starting server in jruby environment...'
260
+ system("#{cmd}")
261
+ else
262
+ puts 'Detach with Ctrl+\ Re-attach with rake rhoconnect:attach'
263
+ sleep 2
264
+ sh "dtach -A #{rhoconnect_socket} #{cmd} config.ru -P #{rhoconnect_pid}"
265
+ end
266
+ end
267
+
268
+ desc "run rhoconnect console"
269
+ task :console, :environment do |t, args|
270
+ if RedisRunner.running?
271
+ #load development environment by default
272
+ ENV['RACK_ENV'] = args[:environment] || 'development'
273
+ sh "irb -rubygems -r #{File.join(File.dirname(__FILE__),'console')} -r #{File.dirname(__FILE__)} -r application"
274
+ else
275
+ puts "Redis is not running. Please start it by running 'rake redis:start' command."
276
+ end
277
+ end
278
+
279
+ desc "Stop rhoconnect server"
280
+ task :stop => :dtach_installed do
281
+ sh "cat #{rhoconnect_pid} | xargs kill -3" unless windows?
282
+ end
283
+
284
+ desc "Attach to rhoconnect console"
285
+ task :attach => :dtach_installed do
286
+ sh "dtach -a #{rhoconnect_socket}" unless windows?
287
+ end
288
+
289
+ desc "Launch the web console in a browser - uses :syncserver: in settings.yml"
290
+ task :web => :config do
291
+ windows? ? sh("start #{$url}") : sh("open #{$url}")
292
+ end
293
+
294
+ desc "Flush data store - WARNING: THIS REMOVES ALL DATA IN RHOCONNECT"
295
+ task :flushdb => :config do
296
+ puts "*** WARNING: THIS WILL REMOVE ALL DATA FROM YOUR REDIS STORE ***"
297
+ confirm = ask "Are you sure (please answer yes/no)? "
298
+ if confirm == 'yes'
299
+ Redis.new.flushdb
300
+ puts "Database flushed..."
301
+ else
302
+ puts "Aborted..."
303
+ end
304
+ end
305
+
306
+ desc "Generate a cryptographically secure secret session key"
307
+ task :secret do
308
+ begin
309
+ require 'securerandom'
310
+ puts SecureRandom.hex(64)
311
+ rescue LoadError
312
+ puts "Missing secure random generator. Try running `rake secret` in a rails application instead."
313
+ end
314
+ end
315
+
316
+ desc "Build executable WAR file to be used in Java App Servers"
317
+ task :war do
318
+ if jruby? then
319
+ puts "building the WAR file"
320
+ if not File::exists? "config/warble.rb"
321
+ puts "generating Warbler's config file"
322
+ includeDirs = []
323
+ Dir.mkdir('config') if not File.exists?('config')
324
+ aFile = File.new("config/warble.rb", "w+")
325
+ if aFile
326
+ includeDirs = FileList['*'].exclude do |entry|
327
+ entry if (not File.directory? entry) || (entry == 'spec')
328
+ end
329
+ configFile = "Warbler::Config.new do |config|\n" +
330
+ "config.dirs = %w(#{includeDirs.join(' ')})\n" +
331
+ "config.includes = FileList[\"./*\"]\n" +
332
+ "config.excludes = FileList[\"./*.war\",'spec']\nend"
333
+ aFile.write("#{configFile}")
334
+ aFile.close
335
+ else
336
+ puts "Unable to create config/warble.rb file!"
337
+ end
338
+ end
339
+ # build the executable WAR using the config/warble.rb file
340
+ ENV['BUNDLE_WITHOUT'] = ['development','test'].join(':')
341
+ sh 'warble executable war'
342
+ else
343
+ puts "Cannot build WAR files outside of JRuby environment!"
344
+ end
345
+ end
346
+ end
347
+
348
+ task :default => ['rhoconnect:spec']
349
+
350
+ load File.join(File.dirname(__FILE__),'..','..','tasks','redis.rake')
@@ -0,0 +1,220 @@
1
+ module Rhoconnect
2
+ class SourceAdapter
3
+ attr_accessor :result
4
+ end
5
+
6
+ module TestMethods
7
+ # Initializes the source adapter under test for a given user, typically in a before(:each) block
8
+ # setup_test_for(Product,'testuser') #=> 'testuser' will be used by rest of the specs
9
+ def setup_test_for(adapter,user_id)
10
+ app_id = 'application'
11
+ s_fields = {
12
+ :user_id => user_id,
13
+ :app_id => app_id
14
+ }
15
+ c_fields = {
16
+ :device_type => 'Apple',
17
+ :device_pin => 'abcd',
18
+ :device_port => '3333',
19
+ :user_id => user_id,
20
+ :app_id => app_id
21
+ }
22
+ @u = User.create(:login => user_id)
23
+ @s = Source.load(adapter.to_s,s_fields)
24
+ @c = Client.create(c_fields,{:source_name => adapter.to_s})
25
+ @ss = SourceSync.new(@s)
26
+ end
27
+
28
+ # Executes the adapter's query method and returns
29
+ # the master document (:md) stored in redis
30
+ # For example, if your source adapter query method was:
31
+ # def query(params=nil)
32
+ # @result = {
33
+ # "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
34
+ # "2"=>{"name"=>"Best", "industry"=>"Software"}
35
+ # }
36
+ # end
37
+ #
38
+ # test_query would return:
39
+ # {
40
+ # "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
41
+ # "2"=>{"name"=>"Best", "industry"=>"Software"}
42
+ # }
43
+ def test_query
44
+ res = @ss.process_query
45
+ return @s.is_pass_through? ? res : md
46
+ end
47
+
48
+ # Executes the adapter's query method and returns
49
+ # the metadata stored in redis
50
+ # For example, if your source adapter metadata method was:
51
+ # def metadata
52
+ # row1 = {
53
+ # :label => 'Address 1',
54
+ # :value => '123 fake street',
55
+ # :name => 'address1',
56
+ # :type => 'labeledrow'
57
+ # }
58
+ # table = {
59
+ # :label => 'Table',
60
+ # :type => 'table',
61
+ # :children => [ row1, row1, row1 ]
62
+ # }
63
+ # view = {
64
+ # :title => 'UI meta panel',
65
+ # :type => 'iuipanel',
66
+ # :children => [table]
67
+ # }
68
+ # return the definition as JSON
69
+ # {'index' => view}.to_json
70
+ #
71
+ # test_metadata would return:
72
+ # {
73
+ # {'index' => view}.to_json
74
+ # }
75
+ def test_metadata
76
+ @ss.process_query
77
+ return @s.get_value(:metadata)
78
+ end
79
+
80
+ # Executes the adapter's schema method and returns
81
+ # the schema stored in redis
82
+ # For example, if your source adapter schema method was:
83
+ # def schema
84
+ # {
85
+ # 'version' => '1.0',
86
+ # 'property' => {
87
+ # 'name' => 'string',
88
+ # 'brand' => 'string',
89
+ # 'price' => 'string',
90
+ # 'image_url_cropped' => 'blob,overwrite',
91
+ # 'image_url' => 'blob'
92
+ # },
93
+ # 'index' => {
94
+ # 'by_name_brand' => 'name,brand'
95
+ # },
96
+ # 'unique_index' => {
97
+ # 'by_price' => 'price'
98
+ # }
99
+ # }.to_json
100
+ # test_schema would return the above
101
+ def test_schema
102
+ @ss.process_query
103
+ return @s.get_value(:schema)
104
+ end
105
+
106
+ # Returns any errors stored in redis for the previous source adapter query
107
+ # For example: {"query-error"=>{"message"=>"error connecting to web service!"}}
108
+ def query_errors
109
+ @s.get_data(:errors)
110
+ end
111
+
112
+ # Execute's the adapter's create method with a provided record and
113
+ # returns the object string from the create method. If the create method
114
+ # returns a string, then a link will be saved for the device next time
115
+ # it synchronizes. This link can be tested here.
116
+ #
117
+ # For example, in your spec:
118
+ # @product = {
119
+ # 'name' => 'iPhone',
120
+ # 'brand' => 'Apple',
121
+ # 'price' => '$299.99',
122
+ # 'quantity' => '5',
123
+ # 'sku' => '1234'
124
+ # }
125
+ # new_product_id = test_create(@product)
126
+ # create_errors.should == {}
127
+ # md[new_product_id].should == @product
128
+ #
129
+ # This will return the result of the adapter's create method. The master
130
+ # document (:md) should also contain the new record.
131
+ def test_create(record)
132
+ if @s.is_pass_through?
133
+ @ss.pass_through_cud({'create'=> {'temp-id' => record}},nil)
134
+ else
135
+ @c.put_data(:create,{'temp-id' => record})
136
+ @ss.process_cud(@c.id)
137
+ links = @c.get_data(:create_links)['temp-id']
138
+ links ? links['l'] : nil
139
+ end
140
+ end
141
+
142
+ # Returns any errors stored in redis from the previous source adapter create
143
+ # (same structure as query errors)
144
+ def create_errors
145
+ @c.get_data(:create_errors)
146
+ end
147
+
148
+ # Execute the source adapter's update method.
149
+ # Takes a record as hash of hashes (object_id => object)
150
+ #
151
+ # For example:
152
+ # test_update({'4' => {'price' => '$199.99'}})
153
+ # update_errors.should == {}
154
+ # test_query
155
+ # md[product_id]['price'].should == '$199.99'
156
+ #
157
+ # This will call the adapter's update method for object_id '4'
158
+ # NOTE: To test the master document, you will need to run def test_query
159
+ # as shown above
160
+ def test_update(record)
161
+ if @s.is_pass_through?
162
+ @ss.pass_through_cud({'update'=> record },nil)
163
+ else
164
+ @c.put_data(:update,record)
165
+ @ss.process_cud(@c.id)
166
+ end
167
+ end
168
+
169
+ # Returns any errors stored in redis from the previous source adapter update
170
+ # (same structure as query errors)
171
+ def update_errors
172
+ @c.get_data(:update_errors)
173
+ end
174
+
175
+ # Execute the source adapter's delete method.
176
+ # Takes a record as hash of hashes (object_id => object)
177
+ #
178
+ # For example:
179
+ # @product = {
180
+ # 'name' => 'iPhone',
181
+ # 'brand' => 'Apple',
182
+ # 'price' => '$299.99',
183
+ # 'quantity' => '5',
184
+ # 'sku' => '1234'
185
+ # }
186
+ # test_delete('4' => @product)
187
+ # delete_errors.should == {}
188
+ # md.should == {}
189
+ #
190
+ # This will call the adapter's delete method for product '4'
191
+ # NOTE: The master document (:md) will be updated and can be
192
+ # verified as shown above.
193
+ def test_delete(record)
194
+ if @s.is_pass_through?
195
+ @ss.pass_through_cud({'delete'=> record },nil)
196
+ else
197
+ @c.put_data(:delete,record)
198
+ @ss.process_cud(@c.id)
199
+ end
200
+ end
201
+
202
+ # Returns any errors stored in redis from the previous source adapter delete
203
+ # (same structure as query errors)
204
+ def delete_errors
205
+ @c.get_data(:delete_errors)
206
+ end
207
+
208
+ # Returns the master document (:md) for the source adapter stored in redis.
209
+ # This is equivalent to the @result hash of hashes structure.
210
+ def md
211
+ @s.get_data(:md)
212
+ end
213
+
214
+ # Returns the client document (:cd) for the source adapter + client under test.
215
+ # The master document (:md) and client document (:cd) should be equal
216
+ def cd
217
+ @c.get_data(:cd)
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,95 @@
1
+ require 'digest/sha1'
2
+
3
+ module Rhoconnect
4
+ # Inspired by sinatra-authentication
5
+ # Password uses simple sha1 digest for hashing
6
+ class User < Model
7
+ field :login,:string
8
+ field :email,:string
9
+ field :salt,:string
10
+ field :hashed_password,:string
11
+ set :clients, :string
12
+ field :admin, :int
13
+ field :token_id, :string
14
+
15
+ class << self
16
+ def create(fields={})
17
+ raise ArgumentError.new("Reserved user id #{fields[:login]}") if fields[:login] && fields[:login] == '__shared__'
18
+ fields[:id] = fields[:login]
19
+ user = super(fields)
20
+ if Rhoconnect.stats
21
+ Rhoconnect::Stats::Record.set('users') { Store.incr('user:count') }
22
+ else
23
+ Store.incr('user:count')
24
+ end
25
+ user
26
+ end
27
+
28
+ def authenticate(login,password)
29
+ return unless is_exist?(login)
30
+ current_user = load(login)
31
+ return if current_user.nil?
32
+ return current_user if User.encrypt(password, current_user.salt) == current_user.hashed_password
33
+ end
34
+ end
35
+
36
+ def new_password=(pass)
37
+ self.password=(pass)
38
+ end
39
+
40
+ def password=(pass)
41
+ @password = pass
42
+ self.salt = User.random_string(10) if !self.salt
43
+ self.hashed_password = User.encrypt(@password, self.salt)
44
+ end
45
+
46
+ def delete
47
+ clients.members.each do |client_id|
48
+ Client.load(client_id,{:source_name => '*'}).delete
49
+ end
50
+ self.token.delete if self.token
51
+ if Rhoconnect.stats
52
+ Rhoconnect::Stats::Record.set('users') { Store.decr('user:count') }
53
+ else
54
+ Store.decr('user:count')
55
+ end
56
+ super
57
+ end
58
+
59
+ def create_token
60
+ if self.token_id && ApiToken.is_exist?(self.token_id)
61
+ self.token.delete
62
+ end
63
+ self.token_id = ApiToken.create(:user_id => self.login).id
64
+ end
65
+
66
+ def token
67
+ ApiToken.load(self.token_id)
68
+ end
69
+
70
+ def token=(value)
71
+ if self.token_id && ApiToken.is_exist?(self.token_id)
72
+ self.token.delete
73
+ end
74
+ self.token_id = ApiToken.create(:user_id => self.login, :value => value).id
75
+ end
76
+
77
+ def update(fields)
78
+ fields.each do |key,value|
79
+ self.send("#{key.to_sym}=", value) unless key == 'login'
80
+ end
81
+ end
82
+
83
+ protected
84
+ def self.encrypt(pass, salt)
85
+ Digest::SHA1.hexdigest(pass+salt)
86
+ end
87
+
88
+ def self.random_string(len)
89
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
90
+ newpass = ""
91
+ 1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
92
+ return newpass
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,3 @@
1
+ module Rhoconnect
2
+ VERSION = '3.0.0.beta1'
3
+ end