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,13 @@
1
+ <html>
2
+ <head>
3
+ <script type="text/javascript">
4
+ window.location="/console/";
5
+ </script>
6
+ <title>Rhoconnect Server</title>
7
+ </head>
8
+ <body>
9
+ <h3>Rhoconnect Server v<%=Rhoconnect::VERSION%> running...</h3>
10
+ <p><a href="/resque/">Resque</a></p>
11
+ <p><a href="/console/">Console</a></p>
12
+ </body>
13
+ </html>
@@ -0,0 +1,286 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..')
2
+ require 'sinatra/base'
3
+ require 'erb'
4
+ require 'json'
5
+ require 'fileutils'
6
+ require 'rhoconnect'
7
+ require 'rhoconnect/x_domain_session_wrapper'
8
+ require 'rhoconnect/cors'
9
+
10
+ module Rhoconnect
11
+
12
+ class ApiException < Exception
13
+ attr_accessor :error_code
14
+ def initialize(error_code,message)
15
+ super(message)
16
+ @error_code = error_code
17
+ end
18
+ end
19
+
20
+ class Server < Sinatra::Base
21
+ libdir = File.dirname(File.expand_path(__FILE__))
22
+ set :views, "#{libdir}/server/views"
23
+ set :public, "#{libdir}/server/public"
24
+ set :static, true
25
+
26
+ # default secret
27
+ @@secret = '<changeme>'
28
+
29
+ # stats middleware disabled by default
30
+ @@stats = false
31
+
32
+ # Setup route and mimetype for bulk data downloads
33
+ # TODO: Figure out why "mime :data, 'application/octet-stream'" doesn't work
34
+ Rack::Mime::MIME_TYPES['.data'] = 'application/octet-stream'
35
+
36
+ include Rhoconnect
37
+
38
+ helpers do
39
+ def request_action
40
+ request.env['PATH_INFO'].split('/').last
41
+ end
42
+
43
+ def check_api_token
44
+ request_action == 'login' or request_action == 'get_api_token' or
45
+ (params[:api_token] and ApiToken.is_exist?(params[:api_token]))
46
+ end
47
+
48
+ def do_login
49
+ begin
50
+ login ? status(200) : status(401)
51
+ rescue LoginException => le
52
+ throw :halt, [401, le.message]
53
+ rescue Exception => e
54
+ throw :halt, [500, e.message]
55
+ end
56
+ end
57
+
58
+ def login_required
59
+ current_user.nil?
60
+ end
61
+
62
+ def login
63
+ if params[:login] == 'rhoadmin'
64
+ user = User.authenticate(params[:login], params[:password])
65
+ elsif current_app and current_app.can_authenticate?
66
+ user = current_app.authenticate(params[:login], params[:password], session)
67
+ end
68
+ if user
69
+ session[:login] = user.login
70
+ session[:app_name] = APP_NAME
71
+ else
72
+ false
73
+ end
74
+ end
75
+
76
+ def logout
77
+ session[:login] = nil
78
+ end
79
+
80
+ def current_user
81
+ if @user.nil? and User.is_exist?(session[:login])
82
+ @user = User.load(session[:login])
83
+ end
84
+ if @user and (@user.admin == 1 || session[:app_name] == APP_NAME)
85
+ @user
86
+ else
87
+ nil
88
+ end
89
+ end
90
+
91
+ def api_user
92
+ if request_action == 'get_api_token' or request_action == 'login'
93
+ current_user
94
+ else
95
+ u = ApiToken.load(params[:api_token])
96
+ raise "Wrong API token - #{params[:api_token].inspect}" unless u
97
+ u.user
98
+ end
99
+ end
100
+
101
+ def current_app
102
+ App.load(APP_NAME)
103
+ end
104
+
105
+ def current_source
106
+ return @source if @source
107
+ user = current_user
108
+ if params[:source_name] and user
109
+ @source = Source.load(params[:source_name],
110
+ {:user_id => user.login,:app_id => APP_NAME})
111
+
112
+ # if source does not exist create one for dynamic adapter
113
+ unless @source
114
+ @source = Source.create({:name => params[:source_name]},{:user_id => user.login, :app_id => APP_NAME})
115
+ current_app.sources << @source.name
116
+ end
117
+ @source
118
+ else
119
+ log "ERROR: Can't load source, no source_name provided.\n"
120
+ nil
121
+ end
122
+ end
123
+
124
+ def current_client
125
+ if @client.nil? and params[:client_id]
126
+ @client = Client.load(params[:client_id].to_s,
127
+ params[:source_name] ? {:source_name => current_source.name} : {:source_name => '*'})
128
+ if @client and current_user and @client.user_id != current_user.login
129
+ @client.switch_user(current_user.login)
130
+ end
131
+ @client
132
+ end
133
+ end
134
+
135
+ def current_client_sync
136
+ ClientSync.new(current_source,current_client,params[:p_size])
137
+ end
138
+
139
+ def catch_all
140
+ begin
141
+ yield
142
+ rescue ApiException => ae
143
+ throw :halt, [ae.error_code, ae.message]
144
+ rescue Exception => e
145
+ log e.message + e.backtrace.join("\n")
146
+ throw :halt, [500, e.message]
147
+ end
148
+ end
149
+
150
+ def mark_deprecated_call_and_reroute(name, namespace, *params)
151
+ namespace_val = namespace.nil? ? "<namespace>" : "#{namespace}"
152
+ http_method = request.get? ? "GET" : "POST"
153
+ warning_message = "Use of the #{http_method} #{request.route} is deprecated. Use #{http_method} /api/#{namespace_val}/#{name} instead."
154
+ response.headers['Warning'] = warning_message
155
+ Rhoconnect.log warning_message
156
+ if namespace != nil
157
+ call env.merge('PATH_INFO' => "/api/#{namespace}/#{name}")
158
+ else
159
+ yield *params
160
+ end
161
+ end
162
+
163
+ def execute_api_call(client_call = false)
164
+ if client_call or check_api_token
165
+ catch_all do
166
+ res = yield params, (client_call ? current_user : api_user), self
167
+ if params.has_key? :warning
168
+ Rhoconnect.log params[:warning]
169
+ response.headers['Warning'] = params[:warning]
170
+ end
171
+ res
172
+ end
173
+ else
174
+ throw :halt, [422, "No API token provided"]
175
+ end
176
+ end
177
+ end
178
+
179
+ # hook into new so we can enable middleware
180
+ def self.new
181
+ if @@stats == true
182
+ use Rhoconnect::Stats::Middleware
183
+ Rhoconnect.stats = true
184
+ end
185
+ use Rack::Session::Cookie,
186
+ :key => 'rhoconnect_session',
187
+ :expire_after => Rhoconnect.cookie_expire,
188
+ :secret => @@secret
189
+ use XDomainSessionWrapper
190
+ use Rack::Cors do |cfg|
191
+ cfg.allow do |allow|
192
+ allow.origins /.*/
193
+ allow.resource '/application', :headers => :any, :methods => [:get, :post, :put, :delete], :credentials => true
194
+ allow.resource '/application/*', :headers => :any, :methods => [:get, :post, :put, :delete], :credentials => true
195
+ allow.resource '/api/application', :headers => :any, :methods => [:get, :post, :put, :delete], :credentials => true
196
+ allow.resource '/api/application/*', :headers => :any, :methods => [:get, :post, :put, :delete], :credentials => true
197
+ end
198
+ end
199
+ super
200
+ end
201
+
202
+ def self.set(option, value=self, &block)
203
+ @@stats = value if option == :stats and (value.is_a?(TrueClass) or value.is_a?(FalseClass))
204
+ @@secret = value if option == :secret and value.is_a?(String)
205
+ super
206
+ end
207
+
208
+ def initialize
209
+ # Whine about default session secret
210
+ check_default_secret!(@@secret)
211
+ super
212
+ end
213
+
214
+ Rhoconnect.log "Rhoconnect Server v#{Rhoconnect::VERSION} started..."
215
+
216
+ before do
217
+ cache_control :no_cache
218
+ headers({'pragma'=>'no-cache'})
219
+
220
+ begin
221
+ if params["cud"]
222
+ cud = JSON.parse(params["cud"])
223
+ params.delete("cud")
224
+ params.merge!(cud)
225
+ end
226
+ #application/json; charset=UTF-8
227
+ if request.env['CONTENT_TYPE'] && request.env['CONTENT_TYPE'].match(/^application\/json/)
228
+ params.merge!(JSON.parse(request.body.read))
229
+ request.body.rewind
230
+ end
231
+ rescue JSON::ParserError => jpe
232
+ log jpe.message + jpe.backtrace.join("\n")
233
+ throw :halt, [500, "Server error while processing client data"]
234
+ rescue Exception => e
235
+ log e.message + e.backtrace.join("\n")
236
+ throw :halt, [500, "Internal server error"]
237
+ end
238
+ if params[:version] and params[:version].to_i < 3
239
+ throw :halt, [404, "Server supports version 3 or higher of the protocol."]
240
+ end
241
+ #log "request params: #{params.inspect}"
242
+ end
243
+
244
+ %w[get post].each do |verb|
245
+ send(verb, "/*application*") do
246
+ unless request_action == 'clientlogin'
247
+ throw :halt, [401, "Not authenticated"] if login_required
248
+ end
249
+ pass
250
+ end
251
+ end
252
+
253
+ get '/' do
254
+ erb :index
255
+ end
256
+
257
+ # Collection routes
258
+ post '/login' do
259
+ mark_deprecated_call_and_reroute(:login, :admin, self, params)
260
+ end
261
+
262
+ # Member routes
263
+ get '/application' do
264
+ mark_deprecated_call_and_reroute(:query, :application, self, params)
265
+ end
266
+
267
+ post '/application' do
268
+ mark_deprecated_call_and_reroute(:queue_updates, :application, self, params)
269
+ end
270
+
271
+ def self.api(name, namespace = nil, verb = :post, &block)
272
+ old_api_prefix = (namespace == :application) ? :application : :api
273
+ client_call = (namespace == :application) ? true : false
274
+ send verb, "/#{old_api_prefix}/#{name}" do
275
+ mark_deprecated_call_and_reroute(name, namespace, &block)
276
+ end
277
+
278
+ send verb, "/api/#{namespace}/#{name}" do
279
+ execute_api_call client_call, &block
280
+ end
281
+ end
282
+ end
283
+ end
284
+
285
+ include Rhoconnect
286
+ Dir[File.join(File.dirname(__FILE__),'api','**','*.rb')].each { |api| load api }
@@ -0,0 +1,289 @@
1
+ module Rhoconnect
2
+ class MemoryModel
3
+ @@model_data = {}
4
+ @@string_fields = []
5
+ @@integer_fields = []
6
+ attr_accessor :id
7
+
8
+ class << self
9
+ attr_accessor :validates_presence
10
+
11
+ def create(fields,params)
12
+ if self.validates_presence
13
+ self.validates_presence.each do |field|
14
+ raise ArgumentError.new("Missing required field '#{field}'") unless fields[field]
15
+ end
16
+ end
17
+ end
18
+
19
+ def define_fields(string_fields = [], integer_fields = [])
20
+ @@string_fields,@@integer_fields = string_fields,integer_fields
21
+ integer_fields.each do |attrib|
22
+ define_method("#{attrib}=") do |value|
23
+ value = (value.nil?) ? nil : value.to_i
24
+ @@model_data[self.name.to_sym][attrib.to_sym] = value
25
+ end
26
+ define_method("#{attrib}") do
27
+ @@model_data[self.name.to_sym][attrib.to_sym]
28
+ end
29
+ end
30
+ string_fields.each do |attrib|
31
+ define_method("#{attrib}=") do |value|
32
+ attrib = attrib.to_sym
33
+ name = nil
34
+ if attrib == :name
35
+ instance_variable_set(:@name, value)
36
+ name = value
37
+ else
38
+ name = self.name
39
+ end
40
+ @@model_data[name.to_sym] ||= {} # TODO: shouldn't be nil here
41
+ @@model_data[name.to_sym][attrib] = value
42
+ end
43
+ define_method("#{attrib}") do
44
+ @@model_data[instance_variable_get(:@name).to_sym][attrib.to_sym]
45
+ end
46
+ # we have separate methods for this
47
+ @@integer_fields << :poll_interval unless @@integer_fields.include?(:poll_interval)
48
+ end
49
+ end
50
+
51
+ def validates_presence_of(*names)
52
+ self.validates_presence ||= []
53
+ names.each do |name|
54
+ self.validates_presence << name
55
+ end
56
+ end
57
+
58
+ def is_exist?(id)
59
+ !@@model_data[id.to_sym].nil?
60
+ end
61
+
62
+ def class_prefix(classname)
63
+ classname.to_s.
64
+ sub(%r{(.*::)}, '').
65
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
66
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
67
+ downcase
68
+ end
69
+ end
70
+
71
+ def to_array
72
+ res = []
73
+ @@string_fields.each do |field|
74
+ res << {"name" => field, "value" => send(field.to_sym), "type" => "string"}
75
+ end
76
+ @@integer_fields.each do |field|
77
+ res << {"name" => field, "value" => send(field.to_sym), "type" => "integer"}
78
+ end
79
+ res
80
+ end
81
+ end
82
+
83
+ class Source < MemoryModel
84
+ attr_accessor :app_id, :user_id
85
+
86
+ validates_presence_of :name
87
+
88
+ include Document
89
+ include LockOps
90
+
91
+ # source fields
92
+ define_fields([:id, :rho__id, :name, :url, :login, :password, :callback_url, :partition_type, :sync_type,
93
+ :queue, :query_queue, :cud_queue, :belongs_to, :has_many, :pass_through], [:source_id, :priority])
94
+
95
+ def initialize(fields)
96
+ self.name = fields['name'] || fields[:name]
97
+ fields.each do |name,value|
98
+ arg = "#{name}=".to_sym
99
+ self.send(arg, value) if self.respond_to?(arg)
100
+ end
101
+ end
102
+
103
+ def self.set_defaults(fields)
104
+ fields[:url] ||= ''
105
+ fields[:login] ||= ''
106
+ fields[:password] ||= ''
107
+ fields[:priority] ||= 3
108
+ fields[:partition_type] = fields[:partition_type] ? fields[:partition_type].to_sym : :user
109
+ fields[:poll_interval] ||= 300
110
+ fields[:sync_type] = fields[:sync_type] ? fields[:sync_type].to_sym : :incremental
111
+ fields[:id] = fields[:name]
112
+ fields[:rho__id] = fields[:name]
113
+ fields[:belongs_to] = fields[:belongs_to].to_json if fields[:belongs_to]
114
+ fields[:schema] = fields[:schema].to_json if fields[:schema]
115
+ end
116
+
117
+ def self.create(fields,params)
118
+ fields = fields.with_indifferent_access # so we can access hash keys as symbols
119
+ super(fields,params)
120
+ @@model_data[fields[:name].to_sym] = {}
121
+ set_defaults(fields)
122
+ obj = new(fields)
123
+ obj.assign_args(params)
124
+ obj
125
+ end
126
+
127
+ def self.load(obj_id,params)
128
+ validate_attributes(params)
129
+ model_hash = @@model_data[obj_id.to_sym]
130
+ obj = new(model_hash) if model_hash
131
+ if obj
132
+ obj = obj.dup
133
+ obj.assign_args(params)
134
+ end
135
+ obj
136
+ end
137
+
138
+ def self.update_associations(sources)
139
+ params = {:app_id => APP_NAME,:user_id => '*'}
140
+ sources.each { |source| Source.load(source, params).has_many = nil }
141
+ sources.each do |source|
142
+ s = Source.load(source, params)
143
+ if s.belongs_to
144
+ belongs_to = JSON.parse(s.belongs_to)
145
+ if belongs_to.is_a?(Array)
146
+ belongs_to.each do |entry|
147
+ attrib = entry.keys[0]
148
+ model = entry[attrib]
149
+ owner = Source.load(model, params)
150
+ owner.has_many ||= ''
151
+ owner.has_many = owner.has_many+',' if owner.has_many.length > 0
152
+ owner.has_many += [source,attrib].join(',')
153
+ end
154
+ else
155
+ log "WARNING: Incorrect belongs_to format for #{source}, belongs_to should be an array."
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ def self.delete_all
162
+ params = {:app_id => APP_NAME,:user_id => '*'}
163
+ @@model_data.each { |k,v| Source.load(k,params).flash_store_data }
164
+ @@model_data = {}
165
+ end
166
+
167
+ def assign_args(params)
168
+ self.user_id = params[:user_id]
169
+ self.app_id = params[:app_id]
170
+ end
171
+
172
+ def blob_attribs
173
+ return '' unless self.schema
174
+ schema = JSON.parse(self.schema)
175
+ blob_attribs = []
176
+ schema['property'].each do |key,value|
177
+ values = value ? value.split(',') : []
178
+ blob_attribs << key if values.include?('blob')
179
+ end
180
+ blob_attribs.sort.join(',')
181
+ end
182
+
183
+ def update(fields)
184
+ fields = fields.with_indifferent_access # so we can access hash keys as symbols
185
+ self.class.set_defaults(fields)
186
+ end
187
+
188
+ def clone(src_doctype,dst_doctype)
189
+ Store.clone(docname(src_doctype),docname(dst_doctype))
190
+ end
191
+
192
+ def poll_interval
193
+ value = Store.get_value(poll_interval_key)
194
+ value ? value.to_i : nil
195
+ end
196
+
197
+ def poll_interval=(interval)
198
+ Store.put_value(poll_interval_key, interval)
199
+ end
200
+
201
+ # Return the user associated with a source
202
+ def user
203
+ User.load(self.user_id)
204
+ end
205
+
206
+ # Return the app the source belongs to
207
+ def app
208
+ App.load(self.app_id)
209
+ end
210
+
211
+ def schema
212
+ self.get_value(:schema)
213
+ end
214
+
215
+ def read_state
216
+ id = {:app_id => self.app_id,:user_id => user_by_partition,
217
+ :source_name => self.name}
218
+ load_read_state || ReadState.create(id)
219
+ end
220
+
221
+ def load_read_state
222
+ id = {:app_id => self.app_id,:user_id => user_by_partition,
223
+ :source_name => self.name}
224
+ ReadState.load(id)
225
+ end
226
+
227
+ def delete_user_read_state
228
+ id = {:app_id => self.app_id,:user_id => user_by_partition,
229
+ :source_name => self.name}
230
+ ReadState.delete_user(id)
231
+ end
232
+
233
+ def doc_suffix(doctype)
234
+ "#{user_by_partition}:#{self.name}:#{doctype.to_s}"
235
+ end
236
+
237
+ def flash_store_data
238
+ delete_user_read_state
239
+ flash_data('*')
240
+ flash_data(poll_interval_key)
241
+ end
242
+
243
+ def delete
244
+ flash_store_data
245
+ @@model_data.delete(rho__id.to_sym) if rho__id
246
+ end
247
+
248
+ def partition
249
+ self.partition_type.to_sym
250
+ end
251
+
252
+ def partition=(value)
253
+ self.partition_type = value
254
+ end
255
+
256
+ def user_by_partition
257
+ self.partition.to_sym == :user ? self.user_id : '__shared__'
258
+ end
259
+
260
+ def check_refresh_time
261
+ self.poll_interval == 0 or
262
+ (self.poll_interval != -1 and self.read_state.refresh_time <= Time.now.to_i)
263
+ end
264
+
265
+ def if_need_refresh(client_id=nil,params=nil)
266
+ need_refresh = lock(:md) do |s|
267
+ check = check_refresh_time
268
+ s.read_state.refresh_time = Time.now.to_i + s.poll_interval if check
269
+ check
270
+ end
271
+ yield client_id,params if need_refresh
272
+ end
273
+
274
+ def is_pass_through?
275
+ self.pass_through and self.pass_through == 'true'
276
+ end
277
+
278
+ private
279
+ def poll_interval_key
280
+ "source:#{self.name}:poll_interval"
281
+ end
282
+
283
+ def self.validate_attributes(params)
284
+ raise ArgumentError.new('Missing required attribute user_id') unless params[:user_id]
285
+ raise ArgumentError.new('Missing required attribute app_id') unless params[:app_id]
286
+ end
287
+
288
+ end
289
+ end
@@ -0,0 +1,123 @@
1
+ module Rhoconnect
2
+ class SourceAdapterException < RuntimeError; end
3
+
4
+ # raise this to cause client to be logged out during a sync
5
+ class SourceAdapterLoginException < SourceAdapterException; end
6
+
7
+ class SourceAdapterLogoffException < SourceAdapterException; end
8
+
9
+ # raise these to trigger rhoconnect sending an error to the client
10
+ class SourceAdapterServerTimeoutException < SourceAdapterException; end
11
+ class SourceAdapterServerErrorException < SourceAdapterException; end
12
+
13
+ class SourceAdapterObjectConflictError < SourceAdapterException; end
14
+
15
+ class SourceAdapter
16
+ attr_accessor :session
17
+
18
+ def initialize(source,credential=nil)
19
+ @source = source
20
+ end
21
+
22
+ def self.create(source,credential=nil)
23
+ adapter=nil
24
+ if source
25
+ begin
26
+ if source.name
27
+ source.name = source.name.dup if source.name.frozen?
28
+ source.name.strip!
29
+ end
30
+ # fix until source adpaters are phased out, checking for Rhoconnect namespace
31
+ # so that backend models with same name as Rhoconnect models are instantiated correctly
32
+ if Object.const_defined?(source.name) && Object.const_get(source.name).to_s.split("::").first != 'Rhoconnect'
33
+ require under_score(source.name)
34
+ adapter=(Object.const_get(source.name)).new(source)
35
+ else
36
+ adapter=DynamicAdapter.new(source)
37
+ end
38
+ rescue ArgumentError => e
39
+ # Backward compatibility with code generated by gems < 2.2.0
40
+ adapter=(Object.const_get(source.name)).new(source,credential)
41
+ log "WARNING: credential parameter in `initialize` method is deprecated and removed in version >= 2.2.0."
42
+ rescue Exception => e
43
+ log "Failure to create adapter from class #{source.name}: #{e.inspect.to_s}"
44
+ raise e
45
+ end
46
+ end
47
+ adapter
48
+ end
49
+
50
+ def login; end
51
+
52
+ def query(params=nil); end
53
+
54
+ def search(params=nil); end
55
+
56
+ def sync
57
+ if @result and @result.empty?
58
+ @source.lock(:md) do |s|
59
+ s.flash_data(:md)
60
+ s.put_value(:md_size,0)
61
+ end
62
+ else
63
+ if @result
64
+ Store.put_data(@tmp_docname,@result)
65
+ @stash_size += @result.size
66
+ end
67
+ @source.lock(:md) do |s|
68
+ s.flash_data(:md)
69
+ Store.rename(@tmp_docname,s.docname(:md))
70
+ s.put_value(:md_size,@stash_size)
71
+ end
72
+ end
73
+ end
74
+
75
+ def do_query(params=nil)
76
+ @tmp_docname = @source.docname(:md) + get_random_uuid
77
+ @stash_size = 0
78
+ params ? self.query(params) : self.query
79
+ if @source.is_pass_through?
80
+ @result
81
+ else
82
+ self.sync
83
+ true
84
+ end
85
+ end
86
+
87
+ def stash_result
88
+ return if @result.nil?
89
+ Store.put_data(@tmp_docname,@result,true)
90
+ @stash_size += @result.size
91
+ @result = nil
92
+ end
93
+
94
+ def expire_bulk_data(partition = :user)
95
+ Rhoconnect.expire_bulk_data(current_user.login,partition)
96
+ end
97
+
98
+ def create(create_hash); end
99
+
100
+ def update(update_hash); end
101
+
102
+ def delete(delete_hash); end
103
+
104
+ def ask(params=nil); end
105
+
106
+ def logoff; end
107
+
108
+ def save(docname)
109
+ return if @result.nil?
110
+ if @result.empty?
111
+ Store.flash_data(docname)
112
+ else
113
+ Store.put_data(docname,@result)
114
+ end
115
+ end
116
+
117
+ protected
118
+ def current_user
119
+ @source.user
120
+ end
121
+
122
+ end
123
+ end