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
data/doc/rest-api.txt ADDED
@@ -0,0 +1,367 @@
1
+ RhoConnect REST API
2
+ ===
3
+ The RhoConnect REST API allows you to control, monitor, and debug a running RhoConnect application using a simple HTTP API.
4
+
5
+ Below we describe the REST API using ruby sample code.
6
+
7
+ ## API Errors
8
+ All API calls will return http 200 and requested data (if applied). Otherwise, API will return http error code and specific error message in the http message body.
9
+
10
+ :::ruby
11
+ def handle_api_error(error_message)
12
+ @errors ||= []
13
+ begin
14
+ yield
15
+ rescue RestClient::Exception => re
16
+ if re.response.body.nil? or re.response.body.length == 0
17
+ @errors << "#{error_message}: [#{re.http_code}] #{re.message}"
18
+ else
19
+ @errors << "#{error_message}: #{re.response.body}"
20
+ end
21
+ rescue Exception => e
22
+ @errors << "#{error_message}: #{e.message}"
23
+ end
24
+ end
25
+
26
+ handle_api_error("Can't get license information") do
27
+ @license_info = JSON.parse(
28
+ RestClient.post(
29
+ "#{server}/api/get_license_info",
30
+ { :api_token => @token }.to_json,
31
+ :content_type => :json
32
+ ).body
33
+ )
34
+ end
35
+
36
+ ## API Methods
37
+
38
+ ### `get_api_token`
39
+ Before you can use RhoConnect API you should get API token:
40
+
41
+ :::ruby
42
+ require 'rest_client'
43
+ require 'json'
44
+
45
+ server = "http://localhost:9292"
46
+ login = "rhoadmin"
47
+ password = ""
48
+
49
+ res = RestClient.post("#{server}/login", { :login => login, :password => password }.to_json, :content_type => :json)
50
+ rhoconnect_session_cookie = 'rhoconnect_session=' + res.cookies['rhoconnect_session']
51
+ token = RestClient.post("#{server}/api/get_api_token",'',{ 'Cookie' => rhoconnect_session_cookie })
52
+
53
+ ### `get_license_info`
54
+ Returns license information of the currently used license
55
+
56
+ :::ruby
57
+ license_info = RestClient.post(
58
+ "#{server}/api/get_license_info",
59
+ {:api_token => token}.to_json, :content_type => :json
60
+ ).body
61
+
62
+ ### `reset`
63
+ Reset the server: flush db and re-bootstrap server
64
+
65
+ :::ruby
66
+ RestClient.post("#{server}/api/reset",
67
+ { :api_token => token }.to_json,
68
+ :content_type => :json
69
+ )
70
+
71
+ ### `ping`
72
+ Sends PUSH message to all devices of the specified user:
73
+
74
+ :::ruby
75
+ # :message - message which will be used to display notification popup dialog on the device
76
+ # :badge - iphone specific badge
77
+ # :sound - name of the sound file to play upon receiving PUSH notification
78
+ # :vibrate - number of seconds to vibrate upon receiving PUSH notification
79
+ # :sources - list of data source names to be synced upon receiving PUSH notification
80
+ ping_params = {
81
+ :api_token => token,
82
+ :user_id => user_id,
83
+ :sources => source_name,
84
+ :message => 'hello world',
85
+ :vibrate => 2000,
86
+ :sound => 'hello.mp3'
87
+ }
88
+
89
+ RestClient.post(
90
+ "#{server}/api/ping",ping_params.to_json,
91
+ :content_type => :json
92
+ )
93
+
94
+ ### `push_objects`
95
+ Push new objects or object updates to RhoConnect. These changes will be sent to device next time it synchronizes.
96
+
97
+ **NOTE: you may use [ping](/rhoconnect/push) to notify client and trigger sync.**
98
+
99
+ :::ruby
100
+ # list of objects in the canonical hash of hashes structure
101
+ data = {
102
+ '5' => {
103
+ 'name' => 'iPhone'
104
+ }
105
+ }
106
+ RestClient.post(
107
+ "#{server}/api/push_objects",
108
+ {
109
+ :api_token => token,
110
+ :user_id => user_id,
111
+ :source_id => source_name,
112
+ :objects => data
113
+ }.to_json,
114
+ :content_type => :json
115
+ )
116
+
117
+ ### `push_deletes`
118
+ Delete objects from RhoConnect. These objects will be deleted from the device the next time it synchronizes.
119
+
120
+ **NOTE: You may use [ping](/rhoconnect/push) to notify client and trigger sync.**
121
+
122
+ :::ruby
123
+ # object_ids is an array of objects to be deleted
124
+ RestClient.post(
125
+ "/api/push_deletes",
126
+ {
127
+ :api_token => api_token,
128
+ :user_id => user_id,
129
+ :source_id => source_name,
130
+ :objects => object_ids
131
+ }.to_json,
132
+ :content_type => :json
133
+ )
134
+
135
+ ### `list_users`
136
+ List users registered with this RhoConnect application.
137
+
138
+ :::ruby
139
+ users = RestClient.post(
140
+ "#{server}/api/list_users",
141
+ { :api_token => token }.to_json,
142
+ :content_type => :json
143
+ ).body
144
+
145
+ ### `create_user`
146
+ Create a user in this RhoConnect application.
147
+
148
+ :::ruby
149
+ RestClient.post("#{server}/api/create_user",
150
+ {
151
+ :api_token => token,
152
+ :attributes => {
153
+ :login => login,
154
+ :password => password
155
+ }
156
+ }.to_json,
157
+ :content_type => :json
158
+ )
159
+
160
+ ### `delete_user`
161
+ Delete User and all associated devices from the RhoConnect application.
162
+
163
+ :::ruby
164
+ RestClient.post(
165
+ "#{server}/api/delete_user",
166
+ {
167
+ :api_token => token,
168
+ :user_id => user_id
169
+ }.to_json,
170
+ :content_type => :json
171
+ )
172
+
173
+ ### `list_clients`
174
+ List clients (devices) associated with given user.
175
+
176
+ :::ruby
177
+ clients = RestClient.post("#{server}/api/list_clients",
178
+ {
179
+ :api_token => token,
180
+ :user_id => user_id
181
+ }.to_json,
182
+ :content_type => :json
183
+ ).body
184
+
185
+ Returns list of client ids.
186
+
187
+ ### `create_client`
188
+ Creates a client (device) for a given user.
189
+
190
+ :::ruby
191
+ RestClient.post(
192
+ "#{server}/api/create_client",
193
+ {
194
+ :api_token => token,
195
+ :user_id => user_id
196
+ }.to_json,
197
+ :content_type => :json
198
+ ).body
199
+
200
+ ### `delete_client`
201
+ Deletes the specified client (device).
202
+
203
+ :::ruby
204
+ RestClient.post(
205
+ "#{server}/api/delete_client",
206
+ {
207
+ :api_token => token,
208
+ :user_id => user_id,
209
+ :client_id => client_id
210
+ }.to_json,
211
+ :content_type => :json
212
+ )
213
+
214
+ ### `get_client_params`
215
+ Returns client (device) attributes, such as `device_type`, `device_pin`, `device_port`. These attributes used by [RhoConnect push](/rhoconnect/push).
216
+
217
+ :::ruby
218
+ RestClient.post(
219
+ "#{server}/api/get_client_params",
220
+ {
221
+ :api_token => token,
222
+ :client_id => client_id
223
+ }.to_json,
224
+ :content_type => :json
225
+ ).body
226
+
227
+ ### `list_client_docs`
228
+ Returns list of document keys associated with particular client. These documents are used by the server to sync data with the client.
229
+ CD (:cd) - client document; represents the state of the client (set of all objects on the given client).
230
+
231
+ :::ruby
232
+ RestClient.post(
233
+ "#{server}/api/list_client_docs",
234
+ {
235
+ :api_token => token,
236
+ :source_id => source_id,
237
+ :client_id => client_id
238
+ }.to_json,
239
+ :content_type => :json
240
+ ).body
241
+
242
+ ### `list_sources`
243
+ Return list of source adapters for this RhoConnect application.
244
+
245
+ :::ruby
246
+ sources = RestClient.post("#{server}/api/list_sources",
247
+ {
248
+ :api_token => token,
249
+ :partition_type => partition
250
+ }.to_json,
251
+ :content_type => :json
252
+ ).body
253
+
254
+ ### `get_source_params`
255
+ Return attributes associated with a given source:
256
+
257
+ * `name` - name of the data source
258
+ * `poll_interval` - query poll interval; defines how often RhoConnect will call source adapter to query for new data, set to -1 to disable polling, 0 to always poll
259
+ * `partition_type` - to share data across all users, set partition to :app; otherwise use `:user` partition (default)
260
+ * `sync_type` - set to `:bulk_only` to disable `:incremental` sync; regular sync is `:incremental` (default)
261
+ * `queue` - name of the queue for both query and create/update/delete (CUD) jobs (used if no specific queues not specified)
262
+ * `query_queue` - name of query queue
263
+ * `cud_queue` - name of CUD queue
264
+
265
+ **NOTE: query or create/update/delete methods of the source adapter will be executed [asynchronously](/rhoconnect/async-jobs) if a queue name is defined.**
266
+
267
+ :::ruby
268
+ attributes = RestClient.post("#{server}/api/get_source_params",
269
+ {
270
+ :api_token => token,
271
+ :source_id => source_id
272
+ }.to_json,
273
+ :content_type => :json
274
+ ).body
275
+
276
+ ### `set_refresh_time`
277
+ Sets source poll interval to "current time plus x seconds".
278
+
279
+ :::ruby
280
+ RestClient.post(
281
+ "/api/set_refresh_time",
282
+ {
283
+ :api_token => @api_token,
284
+ :source_name => source_name,
285
+ :user_name => user,
286
+ :refresh_time => 100
287
+ }.to_json,
288
+ :content_type => :json
289
+ )
290
+
291
+ This will set the refresh time to 100 seconds from the current time. Calling `set_refresh_time` with no `:refresh_time` will trigger a refresh on the sync request for the source.
292
+
293
+ ### `list_source_docs`
294
+ Return list of document keys associated with given source and user.
295
+
296
+ If `:user_id` set to '*', this call will return list of keys for 'shared' documents.
297
+
298
+ MD(:md) - master document; represents state of the backend (set of all objects for the given app/user/source on the backend service).
299
+
300
+ :::ruby
301
+ docs = RestClient.post(
302
+ "#{server}/api/list_source_docs",
303
+ {
304
+ :api_token => token,
305
+ :source_id => source_id,
306
+ :user_id => user_id
307
+ }.to_json,
308
+ :content_type => :json
309
+ ).body
310
+
311
+ ### `get_db_doc`
312
+ Return content of a given document (client or source).
313
+
314
+ :::ruby
315
+ res = RestClient.post(
316
+ "#{server}/api/get_db_doc",
317
+ {
318
+ :api_token => token,
319
+ :doc => doc,
320
+ :data_type => data_type
321
+ }.to_json,
322
+ :content_type => :json
323
+ ).body
324
+
325
+ `:data_type` should be 'string' for the documents containing single string (size or token docs); otherwise this call will return hash of hashes.
326
+
327
+ ### `set_db_doc`
328
+ Sets the content of the specified server document. Data should be either a string or hash of hashes. Data type should be set accordingly.
329
+
330
+ :::ruby
331
+ RestClient.post(
332
+ "#{server}/api/set_db_doc",
333
+ {
334
+ :api_token => token,
335
+ :doc => doc,
336
+ :data => data,
337
+ :data_type => data_type
338
+ }.to_json,
339
+ :content_type => :json
340
+ )
341
+
342
+ ### `stats`
343
+ Retrieves stats for a given metric key:
344
+
345
+ :::ruby
346
+ RestClient.post(
347
+ "#{server}/api/stats",
348
+ {
349
+ :api_token => @api_token,
350
+ :metric => 'foo',
351
+ :start => 0,
352
+ :finish => -1
353
+ }.to_json,
354
+ :content_type => :json
355
+ )
356
+
357
+ Retrieves a list of metric keys matching a given pattern. This supports 'glob' or '*' style pattern matching. For example, all metric keys associated with 'Product' source adapter methods:
358
+
359
+ :::ruby
360
+ RestClient.post(
361
+ "#{server}/api/stats",
362
+ {
363
+ :api_token => @api_token,
364
+ :names => 'sources:*:Product'
365
+ }.to_json,
366
+ :content_type => :json
367
+ )
@@ -0,0 +1,325 @@
1
+ RhoConnect Source Adapters
2
+ ===
3
+
4
+ Connecting to a backend service with RhoConnect requires that you write a small amount of Ruby code for the query, create, update and delete operations of your particular enterprise backend. The collection of the Ruby code for these operations we refer to as a "source" or "source adapter".
5
+
6
+ ## Generate Source Adapter
7
+
8
+ Adding a new source adapter to your RhoConnect application is simple:
9
+
10
+ :::term
11
+ $ cd storeserver
12
+ $ rhoconnect source product
13
+
14
+ This will generate a new ruby class called `sources/product.rb`:
15
+
16
+ :::ruby
17
+ class Product < SourceAdapter
18
+ def initialize(source)
19
+ super(source)
20
+ end
21
+
22
+ def login
23
+ # TODO: Login to your data source here if necessary
24
+ end
25
+
26
+ def query
27
+ # TODO: Query your backend data source and assign the records
28
+ # to a nested hash structure called @result. For example:
29
+ # @result = {
30
+ # "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
31
+ # "2"=>{"name"=>"Best", "industry"=>"Software"}
32
+ # }
33
+ raise SourceAdapterException.new("Please provide some code to read records from the backend data source")
34
+ end
35
+
36
+ def sync
37
+ super
38
+ end
39
+
40
+ def create(create_hash)
41
+ # TODO: Create a new record in your backend data source
42
+ # If your rhodes rhom object contains image/binary data
43
+ # (has the image_uri attribute), then a blob will be provided
44
+ raise "Please provide some code to create a single record in the backend data source using the create_hash"
45
+ end
46
+
47
+ def update(update_hash)
48
+ # TODO: Update an existing record in your backend data source
49
+ raise "Please provide some code to update a single record in the backend data source using the update_hash"
50
+ end
51
+
52
+ def delete(delete_hash)
53
+ # TODO: write some code here if applicable
54
+ # be sure to have a hash key and value for "object"
55
+ # for now, we'll say that its OK to not have a delete operation
56
+ # raise "Please provide some code to delete a single object in the backend application using the object_id"
57
+ end
58
+
59
+ def logoff
60
+ # TODO: Logout from the data source if necessary
61
+ end
62
+ end
63
+
64
+ It also adds a spec file `spec/sources/product_spec.rb` and updates `settings/settings.yml` with the product adapter to the sources section with some default options:
65
+
66
+ :::yaml
67
+ :sources:
68
+ Product:
69
+ :poll_interval: 300
70
+
71
+ ## Source Adapter API
72
+ The source adapter interface is described below, your source adapter can use any of these methods to interact with your backend service.
73
+
74
+ ### `login`
75
+ Login to your backend service (optional).
76
+
77
+ :::ruby
78
+ def login
79
+ MyWebService.login(current_user.login)
80
+ end
81
+
82
+ ### `logoff`
83
+ Logoff from your backend service (optional).
84
+
85
+ :::ruby
86
+ def logoff
87
+ MyWebService.logoff(current_user.login)
88
+ end
89
+
90
+ ### `query(params = nil)`
91
+ Query your backend service and build a hash of hashes (required).
92
+
93
+ **NOTE: This method must assign `@result` to a hash of hashes. If @result is `nil` or `{}`, the master document will be erased from redis.**
94
+
95
+ :::ruby
96
+ def query
97
+ parsed = JSON.parse(RestClient.get("#{@base}.json").body)
98
+
99
+ @result = {}
100
+ parsed.each do |item|
101
+ @result[item["product"]["id"].to_s] = item["product"]
102
+ end if parsed
103
+ end
104
+
105
+ ### `search(params)`
106
+ Search your backend based on params and build a hash of hashes (optional). Similar to query, however the master document accumulates the data in `@result` instead of replacing when it runs.
107
+
108
+ :::ruby
109
+ def search(params)
110
+ parsed = JSON.parse(RestClient.get("#{@base}.json").body)
111
+
112
+ @result = {}
113
+ parsed.each do |item|
114
+ if item["product"]["name"].downcase == params['name'].downcase
115
+ @result[item["product"]["id"].to_s] = item["product"]
116
+ end
117
+ end if parsed
118
+ end
119
+
120
+ Next, you will need to add search to your Rhodes application. For details, see the [Rhodes search section](/rhodes/synchronization#filtering-datasets-with-search).
121
+
122
+ ### `create(create_hash)`
123
+ Create a new record in the backend (optional).
124
+
125
+ **NOTE: RhoConnect can establish a 'link' between the local record id provided by the client and the new record id provided by the backend service. To enable this link, return the new record id as a string.**
126
+
127
+ :::ruby
128
+ def create(create_hash)
129
+ res = MyWebService.create(create_hash)
130
+
131
+ # return new product id so we establish a client link
132
+ res.new_id
133
+ end
134
+
135
+ ### `update(update_hash)`
136
+ Update an existing record in the backend (optional).
137
+
138
+ :::ruby
139
+ def update(update_hash)
140
+ end
141
+
142
+ ### `delete(delete_hash)`
143
+ Delete an existing record in the backend (optional).
144
+
145
+ :::ruby
146
+ def delete(delete_hash)
147
+ MyWebService.delete(delete_hash['id'])
148
+ end
149
+
150
+ ### `current_user`
151
+ Returns the current user which called the adapter. For example, you could filter results for a specific user in your query method:
152
+
153
+ :::ruby
154
+ def query
155
+ @result = MyWebService.get_records_for_user(current_user.login)
156
+ end
157
+
158
+ ### `stash_result`
159
+ Saves the current state of `@result` to redis and assigns it to `nil`. Typically this is used when your adapter has to paginate through backend service data.
160
+
161
+ :::ruby
162
+ def query
163
+ @result = {}
164
+ ('a'..'z').each_with_index do |letter,i|
165
+ @result ||= {}
166
+ @result.merge!( DictionaryService.get_records_for(letter) )
167
+ stash_result if i % 2
168
+ end
169
+ end
170
+
171
+ ## Data Partitioning
172
+ Data is stored in RhoConnect using [redis sets](http://redis.io/commands#set). The `@result` hash from the `query` method is stored in redis and referred to as the Master Document or MD.
173
+
174
+ The MD is referenced in RhoConnect by a corresponding partition. Source adapters can partition data in two ways: user and app. As you might have guessed, user partitioning stores a copy of the source adapter MD for each user (one copy shared across all devices for a user).
175
+
176
+ Likewise, app partitioning stores one copy of the source adapter MD for the entire application (all users and devices share the same data). App partitioning can be particularly useful if you have source adapters which retrieve large amounts of data that is fixed from user to user, for example a global product catalog. Using app partitioning wherever possible ***greatly reduces*** the amount of data in redis.
177
+
178
+ ### User Partition
179
+ User partitioning is the default scheme for source adapters, however you can explicitly define it in `settings/settings.yml` with:
180
+
181
+ :::yaml
182
+ :sources:
183
+ Product:
184
+ :poll_interval: 300
185
+ :partition_type: user
186
+
187
+ ### App Partition
188
+ Enable app partitioning the same way:
189
+
190
+ :::yaml
191
+ :sources:
192
+ Product:
193
+ :poll_interval: 300
194
+ :partition_type: app
195
+
196
+ Now you have a single copy of the `Product` source adapter dataset for all users.
197
+
198
+ ## Pass Through
199
+ RhoConnect provides a simple way to keep data out of redis. If you have sensitive data that you do not want saved in redis, add the pass_through option in settings/settings.yml for each source:
200
+
201
+ :::yaml
202
+ :sources:
203
+ Product:
204
+ :pass_through: true
205
+
206
+ **NOTE: When running query or search the entire data set will be returned from your backend service. **
207
+
208
+ ## Store API
209
+ RhoConnect provides a simple redis interface for saving/retrieving arbitrary data. This is useful if you want to save data in your application to be used later (i.e. in an async job or a subsequent source adapter execution).
210
+
211
+ :::ruby
212
+ Store.put_value('hello','world')
213
+
214
+ Store.get_value('hello') #=> 'world'
215
+
216
+ # You can store nested hashes too!
217
+ Store.put_data(
218
+ 'mydata',
219
+ {
220
+ '1' => { 'hello' => 'world' }
221
+ }
222
+ )
223
+
224
+ Store.get_data('mydata') #=> { '1' => { 'hello' => 'world' } }
225
+
226
+ ## Handling Exceptions
227
+ If your source adapter raises an instance of `SourceAdapterException`, the resulting message will be sent to the client's sync callback(in `@params['error_message']`). See the rhodes [sync exception handling docs](/rhodes/synchronization#handling-exceptions) for more details.
228
+
229
+ You can use `SourceAdapterException` as a convenient way to notify your application of various error conditions.
230
+
231
+ For example, your delete method might check the web service HTTP response code was 200 to make sure the record was deleted:
232
+
233
+ :::ruby
234
+ def delete(delete_hash)
235
+ rest_result = RestClient.delete("#{@base}/#{delete_hash['id']}")
236
+ if rest_result.code != 200
237
+ raise SourceAdapterException.new("Error deleting record.")
238
+ end
239
+ end
240
+
241
+ **NOTE: When your adapter method raises an exception, no data is removed from the adapter's master document.**
242
+
243
+ The following exceptions are provided for convenience:
244
+
245
+ ### `SourceAdapterLoginException`
246
+ Useful to raise in your adapter's login method if it failed.
247
+
248
+ ### `SourceAdapterLogoffException`
249
+ Similar to login, raise this if your adapter's logoff failed.
250
+
251
+ ### `SourceAdapterServerTimeoutException`
252
+ Raise if your backend service connection times out.
253
+
254
+ ### `SourceAdapterServerErrorException`
255
+ Raise this if your backend service returns a non-successful response.
256
+
257
+
258
+ ## Handling Conflicts
259
+
260
+ Handling conflicts in RhoConnect follows the same pattern as handling exceptions. Once your adapter method has detected a conflict, you can raise a `SourceAdapterObjectConflictError` which will be sent to your application's sync callback.
261
+
262
+ ### `SourceAdapterObjectConflictError`
263
+ Raise this if your adapter has detected a conflict.
264
+
265
+ :::ruby
266
+ def update(update_hash)
267
+ obj_id = update_hash['id']
268
+ update_hash.delete('id')
269
+ rest_result = RestClient.put("#{@base}/#{obj_id}",:product => update_hash)
270
+ if rest_result.code != 200
271
+ raise SourceAdapterObjectConflictError.new("Conflict detected updating the object.")
272
+ end
273
+ end
274
+
275
+ ## Sample Adapter
276
+ Here's a complete example of how the completed [product adapter might look](https://github.com/rhomobile/store-server/blob/master/sources/product.rb):
277
+
278
+ :::ruby
279
+ require 'json'
280
+ require 'rest_client'
281
+
282
+ class Product < SourceAdapter
283
+
284
+ def initialize(source)
285
+ @base = 'http://rhostore.heroku.com/products'
286
+ super(source)
287
+ end
288
+
289
+ def query(params=nil)
290
+ rest_result = RestClient.get("#{@base}.json").body
291
+
292
+ if rest_result.code != 200
293
+ raise SourceAdapterException.new("Error connecting!")
294
+ end
295
+ parsed = JSON.parse(rest_result)
296
+
297
+ @result={}
298
+ parsed.each do |item|
299
+ @result[item["product"]["id"].to_s] = item["product"]
300
+ end if parsed
301
+ end
302
+
303
+ def create(create_hash)
304
+ res = RestClient.post(@base,:product => create_hash)
305
+
306
+ # After create we are redirected to the new record.
307
+ # We need to get the id of that record and return
308
+ # it as part of create so rhoconnect can establish a link
309
+ # from its temporary object on the client to this newly
310
+ # created object on the server
311
+ JSON.parse(
312
+ RestClient.get("#{res.headers[:location]}.json").body
313
+ )["product"]["id"]
314
+ end
315
+
316
+ def update(update_hash)
317
+ obj_id = update_hash['id']
318
+ update_hash.delete('id')
319
+ RestClient.put("#{@base}/#{obj_id}",:product => update_hash)
320
+ end
321
+
322
+ def delete(delete_hash)
323
+ RestClient.delete("#{@base}/#{delete_hash['id']}")
324
+ end
325
+ end