rhoconnect 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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,414 @@
1
+ module Rhoconnect
2
+ # Taken from http://github.com/voloko/redis-model
3
+ #
4
+ # Simple models for redis-rb.
5
+
6
+ class Model
7
+ attr_accessor :id
8
+
9
+ def initialize(id=nil)
10
+ self.id = id
11
+ end
12
+
13
+ def redis #:nodoc:
14
+ self.class.redis
15
+ end
16
+
17
+ # Issues delete commands for all defined fields
18
+ def delete(name = nil)
19
+ if name
20
+ redis.del field_key(name.to_s)
21
+ else
22
+ self.class.fields.each do |field|
23
+ redis.del field_key(field[:name])
24
+ end
25
+ end
26
+ end
27
+
28
+ def field_key(name) #:nodoc:
29
+ self.class._field_key(prefix,id,name)
30
+ end
31
+
32
+ # Increment the specified integer field by 1 or the
33
+ # specified amount.
34
+ def increment!(name,amount=1)
35
+ raise ArgumentError, "Only integer fields can be incremented." unless self.class.fields.include?({:name => name.to_s, :type => :integer})
36
+ redis.incr(field_key(name), amount)
37
+ end
38
+
39
+ # Decrement the specified integer field by 1 or the
40
+ # specified amount.
41
+ def decrement!(name,amount=1)
42
+ raise ArgumentError, "Only integer fields can be decremented." unless self.class.fields.include?({:name => name.to_s, :type => :integer})
43
+ redis.decr(field_key(name), amount)
44
+ end
45
+
46
+ def next_id #:nodoc:
47
+ redis.incr "sequence:#{self.prefix}:id"
48
+ end
49
+
50
+ def self.is_exist?(id)
51
+ !redis.get(self._field_key(self._prefix,id,'rho__id')).nil?
52
+ end
53
+
54
+ def to_array
55
+ res = []
56
+ self.class.fields.each do |field|
57
+ res << field.merge!(:value => send(field[:name].to_sym))
58
+ end
59
+ res
60
+ end
61
+
62
+ # TODO: not used anymore
63
+ # def update(attribs)
64
+ # self.class.fields.each do |field|
65
+ # if field[:name] != 'name' and field[:name] != 'rho__id'
66
+ # redis.del field_key(field[:name])
67
+ # end
68
+ # end
69
+ # self.class.populate_attributes(self,attribs)
70
+ # end
71
+
72
+ protected
73
+ def prefix #:nodoc:
74
+ @prefix ||= self.class.prefix || self.class.class_prefix(self.class)
75
+ end
76
+
77
+ class << self
78
+ # Defaults to model_name.dasherize
79
+ attr_accessor :prefix
80
+ attr_accessor :validates_presence
81
+
82
+ def _prefix
83
+ class_prefix(self)
84
+ end
85
+
86
+ def _field_key(p,i,n) #:nodoc:
87
+ "#{p}:#{i}:#{n}"
88
+ end
89
+
90
+ def class_prefix(classname)
91
+ classname.to_s.
92
+ sub(%r{(.*::)}, '').
93
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
94
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
95
+ downcase
96
+ end
97
+
98
+ # Creates new model instance with new uniqid
99
+ # NOTE: "sequence:model_name:id" key is used
100
+ def create(params = {}, attributes = {})
101
+ raise ArgumentError.new("Record already exists for '#{params[:id]}'") if self.is_exist?(params[:id])
102
+ if self.validates_presence
103
+ self.validates_presence.each do |field|
104
+ raise ArgumentError.new("Missing required field '#{field}'") unless params[field]
105
+ end
106
+ end
107
+ o = self.new
108
+ o.id = params[:id].nil? ? o.next_id : params[:id]
109
+ params[:rho__id] = params[:id]
110
+ populate_model(o,params)
111
+ populate_attributes(o,attributes)
112
+ end
113
+
114
+ def load(id, params={})
115
+ populate_attributes(self.with_key(id),params) if self.is_exist?(id)
116
+ end
117
+
118
+ def populate_attributes(obj,attribs)
119
+ attribs.each do |attrib,value|
120
+ obj.send "#{attrib.to_s}=".to_sym, value
121
+ end
122
+ obj
123
+ end
124
+
125
+ def validates_presence_of(*names)
126
+ self.validates_presence ||= []
127
+ names.each do |name|
128
+ self.validates_presence << name
129
+ end
130
+ end
131
+
132
+ # Creates new model instance with given id
133
+ alias_method :with_key, :new
134
+ alias_method :with_next_key, :create
135
+
136
+ # Defines marshaled rw accessor for redis string value
137
+ def field(name, type = :string)
138
+ if @fields.nil?
139
+ @fields = []
140
+ field :rho__id, :string
141
+ end
142
+ type = type.to_sym
143
+ type = :integer if type == :int
144
+
145
+ class_name = marshal_class_name(name, type)
146
+
147
+ fields << {:name => name.to_s, :type => type}
148
+ if type == :string
149
+ class_eval "def #{name}; @#{name} ||= redis[field_key('#{name}')]; end"
150
+ class_eval "def #{name}=(value); @#{name} = redis[field_key('#{name}')] = value; end"
151
+ else
152
+ class_eval "def #{name}; @#{name} ||= Marshal::#{class_name}.load(redis[field_key('#{name}')]); end"
153
+ class_eval "def #{name}=(value); @#{name} = value; redis[field_key('#{name}')] = Marshal::#{class_name}.dump(value); end"
154
+ end
155
+ end
156
+ alias_method :value, :field
157
+
158
+ # Defines accessor for redis list
159
+ def list(name, type = :string)
160
+ class_name = marshal_class_name(name, type)
161
+
162
+ fields << {:name => name.to_s, :type => :list}
163
+ class_eval "def #{name}; @#{name} ||= ListProxy.new(self.redis, field_key('#{name}'), Marshal::#{class_name}); end"
164
+ eval_writer(name)
165
+ end
166
+
167
+ # Defines accessor for redis set
168
+ def set(name, type = :string)
169
+ class_name = marshal_class_name(name, type)
170
+
171
+ fields << {:name => name.to_s, :type => :set}
172
+ class_eval "def #{name}; @#{name} ||= SetProxy.new(self.redis, field_key('#{name}'), Marshal::#{class_name}); end"
173
+ eval_writer(name)
174
+ end
175
+
176
+ def marshal_class_name(name, type)
177
+ Marshal::TYPES[type] or raise ArgumentError.new("Unknown type #{type} for field #{name}")
178
+ end
179
+
180
+ # Redefine this to change connection options
181
+ def redis
182
+ @@redis ||= Store.db
183
+ end
184
+
185
+ def fields #:nodoc:
186
+ @fields ||= []
187
+ end
188
+
189
+ protected
190
+ def eval_writer(name) #:nodoc:
191
+ class_eval <<-END
192
+ def #{name}=(value)
193
+ field = self.#{name};
194
+ if value.respond_to?(:each)
195
+ value.each {|v| field << v}
196
+ else
197
+ field << v
198
+ end
199
+ end
200
+ END
201
+ end
202
+
203
+ def populate_model(model, fields)
204
+ return model if fields.empty?
205
+ fields.each do |name,value|
206
+ model.send("#{name}=", value) if model.respond_to?(name)
207
+ end
208
+ model
209
+ end
210
+ end
211
+
212
+ module Marshal
213
+ TYPES = {
214
+ :string => 'String',
215
+ :integer => 'Integer',
216
+ :float => 'Float',
217
+ :datetime => 'DateTime',
218
+ :json => 'JSON',
219
+ }
220
+
221
+ class String
222
+ def self.dump(v)
223
+ v
224
+ end
225
+
226
+ def self.load(v)
227
+ v
228
+ end
229
+ end
230
+
231
+ class Integer
232
+ def self.dump(v)
233
+ v.to_s
234
+ end
235
+
236
+ def self.load(v)
237
+ v && v.to_i
238
+ end
239
+ end
240
+
241
+ class Float
242
+ def self.dump(v)
243
+ v.to_s
244
+ end
245
+
246
+ def self.load(v)
247
+ v && v.to_f
248
+ end
249
+ end
250
+
251
+ class DateTime
252
+ def self.dump(v)
253
+ v.strftime('%FT%T%z')
254
+ end
255
+
256
+ def self.load(v)
257
+ v && ::DateTime.strptime(v, '%FT%T%z')
258
+ end
259
+ end
260
+
261
+ class JSON
262
+ def self.dump(v)
263
+ ::JSON.dump(v)
264
+ end
265
+
266
+ def self.load(v)
267
+ v && ::JSON.load(v)
268
+ end
269
+ end
270
+ end
271
+
272
+
273
+
274
+ class FieldProxy #:nodoc
275
+ def initialize(redis, name, marshal)
276
+ @redis = redis
277
+ @name = name
278
+ @marshal = marshal
279
+ end
280
+
281
+ # def method_missing(method, *argv)
282
+ # translated_method = translate_method_name(method)
283
+ # raise NoMethodError.new("Method '#{method}' is not defined") unless translated_method
284
+ # @redis.send translated_method, @name, *argv
285
+ # end
286
+ #
287
+ # protected
288
+ # def translate_method_name(m)
289
+ # m
290
+ # end
291
+ end
292
+
293
+
294
+
295
+ class ListProxy < FieldProxy #:nodoc:
296
+ def <<(v)
297
+ @redis.rpush @name, @marshal.dump(v)
298
+ end
299
+ alias_method :push_tail, :<<
300
+
301
+ def push_head(v)
302
+ @redis.lpush @name, @marshal.dump(v)
303
+ end
304
+
305
+ def pop_tail
306
+ @marshal.load(@redis.rpop(@name))
307
+ end
308
+
309
+ def pop_head
310
+ @marshal.load(@redis.lpop(@name))
311
+ end
312
+
313
+ def [](from, to = nil)
314
+ if to.nil?
315
+ @marshal.load(@redis.lindex(@name, from))
316
+ else
317
+ @redis.lrange(@name, from, to).map! { |v| @marshal.load(v) }
318
+ end
319
+ end
320
+ alias_method :range, :[]
321
+
322
+ def []=(index, v)
323
+ @redis.lset(@name, index, @marshal.dump(v))
324
+ end
325
+ alias_method :set, :[]=
326
+
327
+ def include?(v)
328
+ @redis.exists(@name, @marshal.dump(v))
329
+ end
330
+
331
+ def remove(count, v)
332
+ @redis.lrem(@name, count, @marshal.dump(v))
333
+ end
334
+
335
+ # def length
336
+ # @redis.llen(@name)
337
+ # end
338
+ #
339
+ # def trim(from, to)
340
+ # @redis.ltrim(@name, from, to)
341
+ # end
342
+ #
343
+ # def to_s
344
+ # range(0, 100).join(', ')
345
+ # end
346
+ #
347
+ # protected
348
+ # def translate_method_name(m)
349
+ # COMMANDS[m]
350
+ # end
351
+ end
352
+
353
+
354
+
355
+ class SetProxy < FieldProxy #:nodoc:
356
+ # COMMANDS = {
357
+ # :intersect_store => "sinterstore",
358
+ # :union_store => "sunionstore",
359
+ # :diff_store => "sdiffstore",
360
+ # :move => "smove",
361
+ # }
362
+
363
+ def <<(v)
364
+ @redis.sadd @name, @marshal.dump(v)
365
+ end
366
+ alias_method :add, :<<
367
+
368
+ def delete(v)
369
+ @redis.srem @name, @marshal.dump(v)
370
+ end
371
+ alias_method :remove, :delete
372
+
373
+ def include?(v)
374
+ @redis.sismember @name, @marshal.dump(v)
375
+ end
376
+ alias_method :has_key?, :include?
377
+ alias_method :member?, :include?
378
+
379
+ def members
380
+ members = @redis.smembers(@name)
381
+ if members
382
+ members.map { |v| @marshal.load(v) }
383
+ else
384
+ []
385
+ end
386
+ end
387
+
388
+ def intersect(*keys)
389
+ @redis.sinter(@name, *keys).map { |v| @marshal.load(v) }
390
+ end
391
+
392
+ def union(*keys)
393
+ @redis.sunion(@name, *keys).map { |v| @marshal.load(v) }
394
+ end
395
+
396
+ def diff(*keys)
397
+ @redis.sdiff(@name, *keys).map { |v| @marshal.load(v) }
398
+ end
399
+
400
+ # def length
401
+ # @redis.llen(@name)
402
+ # end
403
+ #
404
+ # def to_s
405
+ # members.join(', ')
406
+ # end
407
+ #
408
+ # protected
409
+ # def translate_method_name(m)
410
+ # COMMANDS[m]
411
+ # end
412
+ end
413
+ end
414
+ end
@@ -0,0 +1,56 @@
1
+ require 'rest_client'
2
+
3
+ module Rhoconnect
4
+ class Android
5
+ class StaleAuthToken < Exception; end
6
+ class InvalidAuthToken < Exception; end
7
+ class AndroidPingError < Exception; end
8
+
9
+ def self.ping(params)
10
+ begin
11
+ settings = get_config(Rhoconnect.base_directory)[Rhoconnect.environment]
12
+ authtoken = settings[:authtoken]
13
+
14
+ RestClient.post(
15
+ 'https://android.apis.google.com/c2dm/send', c2d_message(params),
16
+ :authorization => "GoogleLogin auth=#{authtoken}"
17
+ ) do |response, request, result, &block|
18
+ # return exceptions based on response code & body
19
+ case response.code
20
+ when 200
21
+ # TODO: Automate authtoken updates
22
+ if response[:update_client_auth]
23
+ raise StaleAuthToken.new(
24
+ "Stale auth token, please update :authtoken: in settings.yml."
25
+ )
26
+ # body will contain the exception class
27
+ elsif response.body =~ /^Error=(.*)$/
28
+ raise AndroidPingError.new("Android ping error: #{$1 || ''}")
29
+ else
30
+ response.return!(request, result, &block)
31
+ end
32
+ when 401, 403
33
+ raise InvalidAuthToken.new("Invalid auth token, please update :authtoken: in settings.yml.")
34
+ end
35
+ end
36
+ rescue Exception => error
37
+ log error
38
+ log error.backtrace.join("\n")
39
+ raise error
40
+ end
41
+ end
42
+
43
+ def self.c2d_message(params)
44
+ params.reject! {|k,v| v.nil? || v.length == 0}
45
+ data = {}
46
+ data['registration_id'] = params['device_pin']
47
+ data['collapse_key'] = (rand * 100000000).to_i.to_s
48
+ data['data.do_sync'] = params['sources'] ? params['sources'].join(',') : ''
49
+ data['data.alert'] = params['message'] if params['message']
50
+ data['data.vibrate'] = params['vibrate'] if params['vibrate']
51
+ data['data.sound'] = params['sound'] if params['sound']
52
+ data['data.phone_id'] = params['phone_id'] if params['phone_id']
53
+ data
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,52 @@
1
+ require 'socket'
2
+ require 'openssl'
3
+ module Rhoconnect
4
+ class Apple
5
+ def self.ping(params)
6
+ settings = get_config(Rhoconnect.base_directory)[Rhoconnect.environment]
7
+ cert_file = File.join(Rhoconnect.base_directory,settings[:iphonecertfile])
8
+ cert = File.read(cert_file) if File.exists?(cert_file)
9
+ passphrase = settings[:iphonepassphrase]
10
+ host = settings[:iphoneserver]
11
+ port = settings[:iphoneport]
12
+ begin
13
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
14
+ ssl_ctx.key = OpenSSL::PKey::RSA.new(cert, passphrase)
15
+ ssl_ctx.cert = OpenSSL::X509::Certificate.new(cert)
16
+
17
+ socket = TCPSocket.new(host, port)
18
+ ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_ctx)
19
+ ssl_socket.sync = true
20
+ ssl_socket.connect
21
+
22
+ ssl_socket.write(apn_message(params))
23
+ ssl_socket.close
24
+ socket.close
25
+ rescue SocketError => error
26
+ log "Error while sending ping: #{error}"
27
+ raise error
28
+ end
29
+ end
30
+
31
+ # Generates APNS package
32
+ def self.apn_message(params)
33
+ data = {}
34
+ data['aps'] = {}
35
+ data['aps']['alert'] = params['message'] if params['message']
36
+ data['aps']['badge'] = params['badge'].to_i if params['badge']
37
+ data['aps']['sound'] = params['sound'] if params['sound']
38
+ data['aps']['vibrate'] = params['vibrate'] if params['vibrate']
39
+ data['do_sync'] = params['sources'] if params['sources']
40
+ json = data.to_json
41
+ "\0\0 #{[params['device_pin'].delete(' ')].pack('H*')}\0#{json.length.chr}#{json}"
42
+ end
43
+ end
44
+
45
+ # Deprecated - use Apple instead
46
+ class Iphone < Apple
47
+ def self.ping(params)
48
+ log "DEPRECATION WARNING: 'iphone' is a deprecated device_type, use 'apple' instead"
49
+ super(params)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,56 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ module Rhoconnect
4
+ class Blackberry
5
+ def self.ping(params)
6
+ begin
7
+ settings = get_config(Rhoconnect.base_directory)[Rhoconnect.environment]
8
+ host = settings[:mdsserver]
9
+ port = settings[:mdsserverport]
10
+
11
+ headers = { "X-WAP-APPLICATION-ID" => "/",
12
+ "X-RIM-PUSH-DEST-PORT" => params['device_port'],
13
+ "CONTENT-TYPE" => 'multipart/related; type="application/xml"; boundary=asdlfkjiurwghasf'}
14
+
15
+ Net::HTTP.new(host,port).start do |http|
16
+ request = Net::HTTP::Post.new('/pap',headers)
17
+ request.body = pap_message(params)
18
+ http.request(request)
19
+ end
20
+
21
+ rescue Exception => error
22
+ log "Error while sending ping: #{error}"
23
+ raise error
24
+ end
25
+ end
26
+
27
+ def self.pap_message(params)
28
+ data = "do_sync=" + (params['sources'] ? params['sources'].join(',') : "") + "\r\n"
29
+ data << "alert=#{params['message']}\r\n" if params['message']
30
+ data << "vibrate=#{params['vibrate']}\r\n" if params['vibrate']
31
+ data << "sound=#{params['sound']}\r\n" if params['sound']
32
+ post_body = <<-DESC
33
+ --asdlfkjiurwghasf
34
+ Content-Type: application/xml; charset=UTF-8
35
+
36
+ <?xml version="1.0"?>
37
+ <!DOCTYPE pap PUBLIC "-//WAPFORUM//DTD PAP 2.0//EN"
38
+ "http://www.wapforum.org/DTD/pap_2.0.dtd"
39
+ [<?wap-pap-ver supported-versions="2.0"?>]>
40
+ <pap>
41
+ <push-message push-id="pushID:#{(rand * 100000000).to_i.to_s}" ppg-notify-requested-to="http://localhost:7778">
42
+
43
+ <address address-value="WAPPUSH=#{params['device_pin'].to_i.to_s(base=16).upcase}%3A100/TYPE=USER@rim.net"/>
44
+ <quality-of-service delivery-method="preferconfirmed"/>
45
+ </push-message>
46
+ </pap>
47
+ --asdlfkjiurwghasf
48
+ Content-Type: text/plain
49
+
50
+ #{data}
51
+ --asdlfkjiurwghasf--
52
+ DESC
53
+ post_body.gsub!(/\n/,"\r\n")
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ require 'rhoconnect/ping/android'
2
+ require 'rhoconnect/ping/apple'
3
+ require 'rhoconnect/ping/blackberry'
@@ -0,0 +1,31 @@
1
+ module Rhoconnect
2
+ class ReadState < Model
3
+ field :refresh_time, :integer
4
+
5
+ def self.create(fields)
6
+ fields[:id] = get_id(fields)
7
+ fields.delete(:app_id)
8
+ fields.delete(:user_id)
9
+ fields.delete(:source_name)
10
+ fields[:refresh_time] ||= Time.now.to_i
11
+ super(fields,{})
12
+ end
13
+
14
+ def self.load(params)
15
+ super(get_id(params),{})
16
+ end
17
+
18
+ def self.delete(app_id)
19
+ Store.flash_data("#{class_prefix(self)}:#{app_id}:*")
20
+ end
21
+
22
+ def self.delete_user(params)
23
+ Store.flash_data("#{class_prefix(self)}:#{params[:app_id]}:#{params[:user_id]}:#{params[:source_name]}:*")
24
+ end
25
+
26
+ private
27
+ def self.get_id(params)
28
+ "#{params[:app_id]}:#{params[:user_id]}:#{params[:source_name]}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,88 @@
1
+ # This class has dubious semantics and we only have it so that
2
+ # people can write params[:key] instead of params['key']
3
+ # and they get the same value for both keys.
4
+
5
+ module Rhoconnect
6
+ class RhoHashWithIndifferentAccess < Hash
7
+ def initialize(constructor = {})
8
+ if constructor.is_a?(Hash)
9
+ super()
10
+ update(constructor)
11
+ end
12
+ end
13
+
14
+ def default(key = nil)
15
+ if key.is_a?(Symbol) && include?(key = key.to_s)
16
+ self[key]
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ alias_method :regular_writer, :[]= #unless method_defined?(:regular_writer)
23
+ alias_method :regular_update, :update #unless method_defined?(:regular_update)
24
+
25
+ # Assigns a new value to the hash:
26
+ #
27
+ # hash = HashWithIndifferentAccess.new
28
+ # hash[:key] = "value"
29
+ #
30
+ def []=(key, value)
31
+ regular_writer(convert_key(key), convert_value(value))
32
+ end
33
+
34
+ # Updates the instantized hash with values from the second:
35
+ #
36
+ # hash_1 = HashWithIndifferentAccess.new
37
+ # hash_1[:key] = "value"
38
+ #
39
+ # hash_2 = HashWithIndifferentAccess.new
40
+ # hash_2[:key] = "New Value!"
41
+ #
42
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
43
+ #
44
+ def update(other_hash)
45
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
46
+ self
47
+ end
48
+
49
+ alias_method :merge!, :update
50
+
51
+ # Checks the hash for a key matching the argument passed in:
52
+ #
53
+ # hash = HashWithIndifferentAccess.new
54
+ # hash["key"] = "value"
55
+ # hash.key? :key # => true
56
+ # hash.key? "key" # => true
57
+ #
58
+ def key?(key)
59
+ super(convert_key(key))
60
+ end
61
+
62
+ alias_method :include?, :key?
63
+ alias_method :has_key?, :key?
64
+ alias_method :member?, :key?
65
+
66
+ def stringify_keys!; self end
67
+ def symbolize_keys!; self end
68
+ def to_options!; self end
69
+
70
+ protected
71
+ def convert_key(key)
72
+ key.kind_of?(Symbol) ? key.to_s : key
73
+ end
74
+
75
+ def convert_value(value)
76
+ value
77
+ end
78
+ end
79
+ end
80
+
81
+ class Hash
82
+ public
83
+ def with_indifferent_access
84
+ hash = Rhoconnect::RhoHashWithIndifferentAccess.new(self)
85
+ hash.default = self.default
86
+ hash
87
+ end
88
+ end