lanes 0.0.1

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 (391) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.jshintrc +3 -0
  4. data/Gemfile +9 -0
  5. data/Guardfile +15 -0
  6. data/LICENSE-MIT.txt +21 -0
  7. data/README.md +15 -0
  8. data/Rakefile +74 -0
  9. data/bin/lanes +5 -0
  10. data/client/images/ajax-loader.gif +0 -0
  11. data/client/images/dataTables/Sorting icons.psd +0 -0
  12. data/client/images/dataTables/back_disabled.png +0 -0
  13. data/client/images/dataTables/back_enabled.png +0 -0
  14. data/client/images/dataTables/back_enabled_hover.png +0 -0
  15. data/client/images/dataTables/favicon.ico +0 -0
  16. data/client/images/dataTables/forward_disabled.png +0 -0
  17. data/client/images/dataTables/forward_enabled.png +0 -0
  18. data/client/images/dataTables/forward_enabled_hover.png +0 -0
  19. data/client/images/dataTables/loading-background.png +0 -0
  20. data/client/images/dataTables/sort_asc.png +0 -0
  21. data/client/images/dataTables/sort_asc_disabled.png +0 -0
  22. data/client/images/dataTables/sort_both.png +0 -0
  23. data/client/images/dataTables/sort_desc.png +0 -0
  24. data/client/images/dataTables/sort_desc_disabled.png +0 -0
  25. data/client/images/logo-sm.png +0 -0
  26. data/client/javascripts/component/Base.coffee +39 -0
  27. data/client/javascripts/component/ChoicesInput.coffee +47 -0
  28. data/client/javascripts/component/Grid.coffee +199 -0
  29. data/client/javascripts/component/ModalDialog.coffee +44 -0
  30. data/client/javascripts/component/PopOver.coffee +52 -0
  31. data/client/javascripts/component/RadioGroup.coffee +59 -0
  32. data/client/javascripts/component/RecordFinder.coffee +143 -0
  33. data/client/javascripts/component/SelectField.coffee +43 -0
  34. data/client/javascripts/component/TaggedField.coffee +27 -0
  35. data/client/javascripts/component/grid/Editor.coffee +65 -0
  36. data/client/javascripts/component/grid/PopOverEditor.coffee +29 -0
  37. data/client/javascripts/component/grid/RowEditor.coffee +31 -0
  38. data/client/javascripts/component/grid/popover-editor.html +18 -0
  39. data/client/javascripts/component/grid/row-editor.html +16 -0
  40. data/client/javascripts/component/grid.html +4 -0
  41. data/client/javascripts/component/index.js +5 -0
  42. data/client/javascripts/component/modal.html +17 -0
  43. data/client/javascripts/component/popover.html +5 -0
  44. data/client/javascripts/component/record-finder/clause.skr +35 -0
  45. data/client/javascripts/component/record-finder/dialog.skr +4 -0
  46. data/client/javascripts/component/record-finder/field.skr +8 -0
  47. data/client/javascripts/data/Bootstrap.coffee +8 -0
  48. data/client/javascripts/data/ChangeSet.coffee +50 -0
  49. data/client/javascripts/data/Collection.coffee +111 -0
  50. data/client/javascripts/data/Config.coffee +15 -0
  51. data/client/javascripts/data/Model.coffee +269 -0
  52. data/client/javascripts/data/PubSub.coffee +68 -0
  53. data/client/javascripts/data/Query.coffee +184 -0
  54. data/client/javascripts/data/Roles.coffee +91 -0
  55. data/client/javascripts/data/Screens.coffee +157 -0
  56. data/client/javascripts/data/Sync.coffee +62 -0
  57. data/client/javascripts/data/User.coffee +70 -0
  58. data/client/javascripts/data/index.js +7 -0
  59. data/client/javascripts/data/mixins/HasCodeField.coffee +13 -0
  60. data/client/javascripts/extension/Base.coffee +9 -0
  61. data/client/javascripts/extension/Extensions.coffee +17 -0
  62. data/client/javascripts/extension/GlAccounts.coffee +9 -0
  63. data/client/javascripts/extension/index.js +6 -0
  64. data/client/javascripts/extension/load.js.erb +3 -0
  65. data/client/javascripts/lanes-complete.js +3 -0
  66. data/client/javascripts/lanes-workspace.js +1 -0
  67. data/client/javascripts/lib/MakeBaseClass.coffee +55 -0
  68. data/client/javascripts/lib/ModuleSupport.coffee +22 -0
  69. data/client/javascripts/lib/Templates.coffee +47 -0
  70. data/client/javascripts/lib/create-namespace.js +0 -0
  71. data/client/javascripts/lib/debounce.coffee +15 -0
  72. data/client/javascripts/lib/defer.coffee +7 -0
  73. data/client/javascripts/lib/el.js +115 -0
  74. data/client/javascripts/lib/index.js +9 -0
  75. data/client/javascripts/lib/loader.coffee +95 -0
  76. data/client/javascripts/lib/namespace.coffee +9 -0
  77. data/client/javascripts/lib/noConflict.coffee +14 -0
  78. data/client/javascripts/lib/promise_helpers.coffee +4 -0
  79. data/client/javascripts/lib/results.coffee +15 -0
  80. data/client/javascripts/lib/underscore.inflection.js +210 -0
  81. data/client/javascripts/lib/utilFunctions.coffee +51 -0
  82. data/client/javascripts/plugins/ResizeSensor.js +144 -0
  83. data/client/javascripts/plugins/index.js +4 -0
  84. data/client/javascripts/plugins/overlay.coffee +41 -0
  85. data/client/javascripts/plugins/trigger.coffee +15 -0
  86. data/client/javascripts/vendor/bootstrap/affix.js +142 -0
  87. data/client/javascripts/vendor/bootstrap/alert.js +92 -0
  88. data/client/javascripts/vendor/bootstrap/button.js +110 -0
  89. data/client/javascripts/vendor/bootstrap/carousel.js +223 -0
  90. data/client/javascripts/vendor/bootstrap/collapse.js +170 -0
  91. data/client/javascripts/vendor/bootstrap/dropdown.js +151 -0
  92. data/client/javascripts/vendor/bootstrap/modal.js +280 -0
  93. data/client/javascripts/vendor/bootstrap/popover.js +113 -0
  94. data/client/javascripts/vendor/bootstrap/scrollspy.js +170 -0
  95. data/client/javascripts/vendor/bootstrap/tab.js +128 -0
  96. data/client/javascripts/vendor/bootstrap/tooltip.js +457 -0
  97. data/client/javascripts/vendor/bootstrap/transition.js +59 -0
  98. data/client/javascripts/vendor/dataTables/dataTables.bootstrap.js +156 -0
  99. data/client/javascripts/vendor/dataTables/dataTables.scroller.js +1185 -0
  100. data/client/javascripts/vendor/dataTables/datatables.responsive.js +666 -0
  101. data/client/javascripts/vendor/dataTables/index.js +2 -0
  102. data/client/javascripts/vendor/dataTables/jquery.dataTables.js +14380 -0
  103. data/client/javascripts/vendor/jquery-2.js +9190 -0
  104. data/client/javascripts/vendor/jquery.tap.js +401 -0
  105. data/client/javascripts/vendor/magicsuggest.js +1565 -0
  106. data/client/javascripts/vendor/message-bus.js +285 -0
  107. data/client/javascripts/vendor/modern-stack.js +14 -0
  108. data/client/javascripts/vendor/packaged.js +13769 -0
  109. data/client/javascripts/view/Assets.coffee +9 -0
  110. data/client/javascripts/view/Base.coffee +231 -0
  111. data/client/javascripts/view/FormBindings.coffee +98 -0
  112. data/client/javascripts/view/Functions.coffee +13 -0
  113. data/client/javascripts/view/Helpers.coffee +77 -0
  114. data/client/javascripts/view/InterfaceState.coffee +88 -0
  115. data/client/javascripts/view/Keys.coffee +59 -0
  116. data/client/javascripts/view/ModelObserver.coffee +31 -0
  117. data/client/javascripts/view/ModelUpdate.coffee +8 -0
  118. data/client/javascripts/view/PubSub.coffee +29 -0
  119. data/client/javascripts/view/RenderContext.coffee +32 -0
  120. data/client/javascripts/view/SaveNotify.coffee +30 -0
  121. data/client/javascripts/view/Screen.coffee +30 -0
  122. data/client/javascripts/view/TimedHighlight.coffee +38 -0
  123. data/client/javascripts/view/TimedMask.coffee +65 -0
  124. data/client/javascripts/view/_button.html +3 -0
  125. data/client/javascripts/view/_toolbar.html +27 -0
  126. data/client/javascripts/view/index.js +10 -0
  127. data/client/javascripts/view/mixins/ScreenChangeListener.coffee +43 -0
  128. data/client/javascripts/view/model-update.html +13 -0
  129. data/client/javascripts/view/screen-definitions.js.erb +7 -0
  130. data/client/javascripts/workspace/ActiveScreensSwitcher.coffee +117 -0
  131. data/client/javascripts/workspace/Instance.es6 +60 -0
  132. data/client/javascripts/workspace/Layout.coffee +18 -0
  133. data/client/javascripts/workspace/LoginDialog.coffee +33 -0
  134. data/client/javascripts/workspace/Navbar.coffee +44 -0
  135. data/client/javascripts/workspace/Pages.coffee +46 -0
  136. data/client/javascripts/workspace/ScreensMenu.coffee +126 -0
  137. data/client/javascripts/workspace/index.js +12 -0
  138. data/client/javascripts/workspace/layout.html +4 -0
  139. data/client/javascripts/workspace/login-dialog.html +16 -0
  140. data/client/javascripts/workspace/menu.html +356 -0
  141. data/client/javascripts/workspace/menu_toggle.html +9 -0
  142. data/client/javascripts/workspace/navbar.html +19 -0
  143. data/client/javascripts/workspace/pages.html +6 -0
  144. data/client/javascripts/workspace/screens-menu.html +11 -0
  145. data/client/javascripts/workspace/screens-switcher.html +7 -0
  146. data/client/javascripts/workspace/tab.html +0 -0
  147. data/client/screens/user-management/UserEditScreen.coffee +21 -0
  148. data/client/screens/user-management/UserManagement.coffee +24 -0
  149. data/client/screens/user-management/grid-popover-editor.html +33 -0
  150. data/client/screens/user-management/index.css +4 -0
  151. data/client/screens/user-management/index.js +2 -0
  152. data/client/screens/user-management/user-management-styles.scss +7 -0
  153. data/client/screens/user-management/user-management.html +8 -0
  154. data/client/stylesheets/compoonents/all.scss +6 -0
  155. data/client/stylesheets/compoonents/changes-notification.scss +44 -0
  156. data/client/stylesheets/compoonents/grid-editors.scss +65 -0
  157. data/client/stylesheets/compoonents/grid.scss +301 -0
  158. data/client/stylesheets/compoonents/modal-dialog.scss +23 -0
  159. data/client/stylesheets/compoonents/record-finder.scss +71 -0
  160. data/client/stylesheets/compoonents/suggest.scss +266 -0
  161. data/client/stylesheets/fonts/icomoon.eot +0 -0
  162. data/client/stylesheets/fonts/icomoon.svg +160 -0
  163. data/client/stylesheets/fonts/icomoon.ttf +0 -0
  164. data/client/stylesheets/fonts/icomoon.woff +0 -0
  165. data/client/stylesheets/fonts/selection.json +3565 -0
  166. data/client/stylesheets/fonts/style.css +451 -0
  167. data/client/stylesheets/fonts.scss +38 -0
  168. data/client/stylesheets/forms.scss +75 -0
  169. data/client/stylesheets/index.css +4 -0
  170. data/client/stylesheets/keybindings.scss +6 -0
  171. data/client/stylesheets/lanes-workspace.scss +17 -0
  172. data/client/stylesheets/layout.scss +272 -0
  173. data/client/stylesheets/plugins/all.scss +2 -0
  174. data/client/stylesheets/plugins/overlay.scss +63 -0
  175. data/client/stylesheets/plugins/resize-sensor.scss +24 -0
  176. data/client/stylesheets/screens.scss +66 -0
  177. data/client/stylesheets/tabs.scss +148 -0
  178. data/client/stylesheets/vendor/bootstrap/_alerts.scss +68 -0
  179. data/client/stylesheets/vendor/bootstrap/_badges.scss +57 -0
  180. data/client/stylesheets/vendor/bootstrap/_breadcrumbs.scss +26 -0
  181. data/client/stylesheets/vendor/bootstrap/_button-groups.scss +240 -0
  182. data/client/stylesheets/vendor/bootstrap/_buttons.scss +157 -0
  183. data/client/stylesheets/vendor/bootstrap/_carousel.scss +243 -0
  184. data/client/stylesheets/vendor/bootstrap/_close.scss +35 -0
  185. data/client/stylesheets/vendor/bootstrap/_code.scss +68 -0
  186. data/client/stylesheets/vendor/bootstrap/_component-animations.scss +35 -0
  187. data/client/stylesheets/vendor/bootstrap/_dropdowns.scss +215 -0
  188. data/client/stylesheets/vendor/bootstrap/_forms.scss +538 -0
  189. data/client/stylesheets/vendor/bootstrap/_glyphicons.scss +237 -0
  190. data/client/stylesheets/vendor/bootstrap/_grid.scss +84 -0
  191. data/client/stylesheets/vendor/bootstrap/_input-groups.scss +166 -0
  192. data/client/stylesheets/vendor/bootstrap/_jumbotron.scss +48 -0
  193. data/client/stylesheets/vendor/bootstrap/_labels.scss +66 -0
  194. data/client/stylesheets/vendor/bootstrap/_list-group.scss +132 -0
  195. data/client/stylesheets/vendor/bootstrap/_media.scss +56 -0
  196. data/client/stylesheets/vendor/bootstrap/_mixins.scss +39 -0
  197. data/client/stylesheets/vendor/bootstrap/_modals.scss +150 -0
  198. data/client/stylesheets/vendor/bootstrap/_navbar.scss +659 -0
  199. data/client/stylesheets/vendor/bootstrap/_navs.scss +242 -0
  200. data/client/stylesheets/vendor/bootstrap/_normalize.scss +425 -0
  201. data/client/stylesheets/vendor/bootstrap/_pager.scss +55 -0
  202. data/client/stylesheets/vendor/bootstrap/_pagination.scss +88 -0
  203. data/client/stylesheets/vendor/bootstrap/_panels.scss +243 -0
  204. data/client/stylesheets/vendor/bootstrap/_popovers.scss +133 -0
  205. data/client/stylesheets/vendor/bootstrap/_print.scss +101 -0
  206. data/client/stylesheets/vendor/bootstrap/_progress-bars.scss +105 -0
  207. data/client/stylesheets/vendor/bootstrap/_responsive-embed.scss +34 -0
  208. data/client/stylesheets/vendor/bootstrap/_responsive-utilities.scss +174 -0
  209. data/client/stylesheets/vendor/bootstrap/_scaffolding.scss +150 -0
  210. data/client/stylesheets/vendor/bootstrap/_tables.scss +233 -0
  211. data/client/stylesheets/vendor/bootstrap/_theme.scss +258 -0
  212. data/client/stylesheets/vendor/bootstrap/_thumbnails.scss +38 -0
  213. data/client/stylesheets/vendor/bootstrap/_tooltip.scss +95 -0
  214. data/client/stylesheets/vendor/bootstrap/_type.scss +304 -0
  215. data/client/stylesheets/vendor/bootstrap/_utilities.scss +57 -0
  216. data/client/stylesheets/vendor/bootstrap/_variables.scss +850 -0
  217. data/client/stylesheets/vendor/bootstrap/_wells.scss +29 -0
  218. data/client/stylesheets/vendor/bootstrap/bootstrap.scss +50 -0
  219. data/client/stylesheets/vendor/bootstrap/mixins/_alerts.scss +14 -0
  220. data/client/stylesheets/vendor/bootstrap/mixins/_background-variant.scss +11 -0
  221. data/client/stylesheets/vendor/bootstrap/mixins/_border-radius.scss +18 -0
  222. data/client/stylesheets/vendor/bootstrap/mixins/_buttons.scss +50 -0
  223. data/client/stylesheets/vendor/bootstrap/mixins/_center-block.scss +7 -0
  224. data/client/stylesheets/vendor/bootstrap/mixins/_clearfix.scss +22 -0
  225. data/client/stylesheets/vendor/bootstrap/mixins/_forms.scss +84 -0
  226. data/client/stylesheets/vendor/bootstrap/mixins/_gradients.scss +58 -0
  227. data/client/stylesheets/vendor/bootstrap/mixins/_grid-framework.scss +81 -0
  228. data/client/stylesheets/vendor/bootstrap/mixins/_grid.scss +122 -0
  229. data/client/stylesheets/vendor/bootstrap/mixins/_hide-text.scss +21 -0
  230. data/client/stylesheets/vendor/bootstrap/mixins/_image.scss +34 -0
  231. data/client/stylesheets/vendor/bootstrap/mixins/_labels.scss +12 -0
  232. data/client/stylesheets/vendor/bootstrap/mixins/_list-group.scss +31 -0
  233. data/client/stylesheets/vendor/bootstrap/mixins/_nav-divider.scss +10 -0
  234. data/client/stylesheets/vendor/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  235. data/client/stylesheets/vendor/bootstrap/mixins/_opacity.scss +8 -0
  236. data/client/stylesheets/vendor/bootstrap/mixins/_pagination.scss +23 -0
  237. data/client/stylesheets/vendor/bootstrap/mixins/_panels.scss +24 -0
  238. data/client/stylesheets/vendor/bootstrap/mixins/_progress-bar.scss +10 -0
  239. data/client/stylesheets/vendor/bootstrap/mixins/_reset-filter.scss +8 -0
  240. data/client/stylesheets/vendor/bootstrap/mixins/_resize.scss +6 -0
  241. data/client/stylesheets/vendor/bootstrap/mixins/_responsive-visibility.scss +21 -0
  242. data/client/stylesheets/vendor/bootstrap/mixins/_size.scss +10 -0
  243. data/client/stylesheets/vendor/bootstrap/mixins/_tab-focus.scss +9 -0
  244. data/client/stylesheets/vendor/bootstrap/mixins/_table-row.scss +28 -0
  245. data/client/stylesheets/vendor/bootstrap/mixins/_text-emphasis.scss +11 -0
  246. data/client/stylesheets/vendor/bootstrap/mixins/_text-overflow.scss +8 -0
  247. data/client/stylesheets/vendor/bootstrap/mixins/_vendor-prefixes.scss +219 -0
  248. data/client/stylesheets/vendor/bootstrap-custom-grid.scss +85 -0
  249. data/client/stylesheets/vendor/bootstrap-custom-modals.scss +150 -0
  250. data/client/stylesheets/vendor/bootstrap.scss +69 -0
  251. data/client/stylesheets/vendor/dataTables.scss +4 -0
  252. data/config/database.yml +9 -0
  253. data/config/puma.rb +7 -0
  254. data/config.ru +4 -0
  255. data/db/migrate/20140615031600_create_hip_users.rb +17 -0
  256. data/db/seed.rb +37 -0
  257. data/foo/Gemfile +5 -0
  258. data/foo/Guardfile +13 -0
  259. data/foo/foo/Gemfile +5 -0
  260. data/foo/foo/lib/foo.rb +7 -0
  261. data/foo/lib/foo/version.rb +3 -0
  262. data/foo/lib/foo.rb +8 -0
  263. data/lanes.gemspec +54 -0
  264. data/lib/generators/lanes/migrations/install_generator.rb +42 -0
  265. data/lib/lanes/access/locked_fields.rb +43 -0
  266. data/lib/lanes/access/role.rb +58 -0
  267. data/lib/lanes/access/role_collection.rb +75 -0
  268. data/lib/lanes/access/roles/administrator.rb +25 -0
  269. data/lib/lanes/access/roles/support.rb +13 -0
  270. data/lib/lanes/access/user_maint_screen.rb +32 -0
  271. data/lib/lanes/access.rb +50 -0
  272. data/lib/lanes/api/asset_pipeline.rb +59 -0
  273. data/lib/lanes/api/authentication_helper.rb +21 -0
  274. data/lib/lanes/api/authentication_provider.rb +45 -0
  275. data/lib/lanes/api/controller.rb +290 -0
  276. data/lib/lanes/api/default_routes.rb +35 -0
  277. data/lib/lanes/api/eco.js +516 -0
  278. data/lib/lanes/api/error_formatter.rb +37 -0
  279. data/lib/lanes/api/helper_methods.rb +32 -0
  280. data/lib/lanes/api/javascript_processor.rb +116 -0
  281. data/lib/lanes/api/pub_sub.rb +33 -0
  282. data/lib/lanes/api/request_wrapper.rb +42 -0
  283. data/lib/lanes/api/root.rb +103 -0
  284. data/lib/lanes/api/skr_templates.rb +60 -0
  285. data/lib/lanes/api/test_specs.rb +59 -0
  286. data/lib/lanes/api/updates.rb +38 -0
  287. data/lib/lanes/api.rb +27 -0
  288. data/lib/lanes/cli.rb +13 -0
  289. data/lib/lanes/concerns/all.rb +16 -0
  290. data/lib/lanes/concerns/api_path.rb +21 -0
  291. data/lib/lanes/concerns/association_extensions.rb +85 -0
  292. data/lib/lanes/concerns/attr_accessor_with_default.rb +62 -0
  293. data/lib/lanes/concerns/code_identifier.rb +43 -0
  294. data/lib/lanes/concerns/export_associations.rb +52 -0
  295. data/lib/lanes/concerns/export_join_tables.rb +39 -0
  296. data/lib/lanes/concerns/export_methods.rb +104 -0
  297. data/lib/lanes/concerns/export_scope.rb +66 -0
  298. data/lib/lanes/concerns/exported_limit_evaluator.rb +17 -0
  299. data/lib/lanes/concerns/immutable_model.rb +32 -0
  300. data/lib/lanes/concerns/locked_fields.rb +84 -0
  301. data/lib/lanes/concerns/pub_sub.rb +105 -0
  302. data/lib/lanes/concerns/queries.rb +20 -0
  303. data/lib/lanes/concerns/random_hash_code.rb +40 -0
  304. data/lib/lanes/concerns/sanitize_api_data.rb +15 -0
  305. data/lib/lanes/concerns/set_attribute_data.rb +154 -0
  306. data/lib/lanes/concerns/track_modifications.rb +51 -0
  307. data/lib/lanes/concerns/visible_id_identifier.rb +53 -0
  308. data/lib/lanes/configuration.rb +85 -0
  309. data/lib/lanes/db/migration_helpers.rb +178 -0
  310. data/lib/lanes/db/migrations.rb +13 -0
  311. data/lib/lanes/db/seed.rb +27 -0
  312. data/lib/lanes/db.rb +86 -0
  313. data/lib/lanes/environment.rb +19 -0
  314. data/lib/lanes/extension.rb +72 -0
  315. data/lib/lanes/generators/app/Gemfile +5 -0
  316. data/lib/lanes/generators/app/Guardfile +13 -0
  317. data/lib/lanes/generators/app/Rakefile +9 -0
  318. data/lib/lanes/generators/app/config/database.yml +9 -0
  319. data/lib/lanes/generators/app/config.ru +4 -0
  320. data/lib/lanes/generators/app/lib/main_class/version.rb +3 -0
  321. data/lib/lanes/generators/app/lib/main_class.rb +8 -0
  322. data/lib/lanes/generators/app.rb +36 -0
  323. data/lib/lanes/guard_tasks.rb +44 -0
  324. data/lib/lanes/logger.rb +37 -0
  325. data/lib/lanes/model.rb +26 -0
  326. data/lib/lanes/numbers.rb +72 -0
  327. data/lib/lanes/rails_engine.rb +5 -0
  328. data/lib/lanes/screens.rb +126 -0
  329. data/lib/lanes/spec_asset_expander.rb +43 -0
  330. data/lib/lanes/strings.rb +56 -0
  331. data/lib/lanes/user.rb +127 -0
  332. data/lib/lanes/validators/all.rb +2 -0
  333. data/lib/lanes/validators/email.rb +17 -0
  334. data/lib/lanes/validators/set.rb +18 -0
  335. data/lib/lanes/version.rb +5 -0
  336. data/lib/lanes.rb +22 -0
  337. data/npm-build/README +1 -0
  338. data/npm-build/compile.coffee +15 -0
  339. data/npm-build/package.json +59 -0
  340. data/npm-build/shims/underscore.js +1416 -0
  341. data/npm-build/template.js +33 -0
  342. data/public/javascripts/jasmine_examples/Player.js +22 -0
  343. data/public/javascripts/jasmine_examples/Song.js +7 -0
  344. data/spec/api/javascript_processor_spec.rb +107 -0
  345. data/spec/api/user_spec.rb +52 -0
  346. data/spec/client/component/ChoicesInputSpec.coffee +12 -0
  347. data/spec/client/component/foo_spec.coffee +4 -0
  348. data/spec/client/foo_spec.js +0 -0
  349. data/spec/client/jasmine_examples/PlayerSpec.js +0 -0
  350. data/spec/client/support/jasmine.yml +128 -0
  351. data/spec/client/support/jasmine_helper.rb +15 -0
  352. data/spec/concerns/api_path_spec.rb +14 -0
  353. data/spec/concerns/association_extensions_spec.rb +30 -0
  354. data/spec/concerns/attr_accessor_with_default_spec.rb +57 -0
  355. data/spec/concerns/code_identifier_spec.rb +45 -0
  356. data/spec/concerns/export_associations_spec.rb +7 -0
  357. data/spec/concerns/export_methods_spec.rb +43 -0
  358. data/spec/concerns/export_scope_spec.rb +15 -0
  359. data/spec/concerns/exported_limits_spec.rb +47 -0
  360. data/spec/concerns/pub_sub_spec.rb +83 -0
  361. data/spec/concerns/set_attribute_data_spec.rb +66 -0
  362. data/spec/configuration_spec.rb +26 -0
  363. data/spec/fixtures/lanes/users.yml +13 -0
  364. data/spec/helpers/.gitkeep +0 -0
  365. data/spec/helpers/SpecHelper.js +18 -0
  366. data/spec/locked_fields_spec.rb +27 -0
  367. data/spec/numbers_spec.rb +26 -0
  368. data/spec/role_collection_spec.rb +19 -0
  369. data/spec/spec_helper.rb +163 -0
  370. data/spec/strings_spec.rb +41 -0
  371. data/spec/testing_models.rb +54 -0
  372. data/spec/user_role_spec.rb +7 -0
  373. data/spec/user_spec.rb +53 -0
  374. data/tasks/migrations.rake +22 -0
  375. data/tasks/publish.rake +8 -0
  376. data/views/index.erb +29 -0
  377. data/views/specs.erb +25 -0
  378. data/yard_ext/all.rb +9 -0
  379. data/yard_ext/code_identifier_handler.rb +33 -0
  380. data/yard_ext/concern_meta_methods.rb +60 -0
  381. data/yard_ext/config_options.rb +27 -0
  382. data/yard_ext/exported_scope.rb +4 -0
  383. data/yard_ext/immutable_handler.rb +17 -0
  384. data/yard_ext/json_attr_accessor.rb +22 -0
  385. data/yard_ext/locked_fields_handler.rb +21 -0
  386. data/yard_ext/templates/default/layout/html/layout.erb +20 -0
  387. data/yard_ext/templates/default/method_details/html/github_link.erb +1 -0
  388. data/yard_ext/templates/default/method_details/setup.rb +3 -0
  389. data/yard_ext/validators.rb +1 -0
  390. data/yard_ext/visible_id_handler.rb +38 -0
  391. metadata +772 -0
@@ -0,0 +1,21 @@
1
+ module Lanes
2
+ module API
3
+ module AuthenticationHelper
4
+ def authenticate!(model, type)
5
+ authentication = Lanes::API.config.authentication_provider.new(environment:env, params:params)
6
+ unless authentication.allowed_access_to?(model, type)
7
+ error!({ errors: {user: "Access Denied"}, message: @authentication.error_message }, 401)
8
+ end
9
+ @authentication
10
+ end
11
+
12
+ def authentication
13
+ @authentication
14
+ end
15
+
16
+ def session
17
+ env['rack.session']
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+ module Lanes
2
+ module API
3
+ class AuthenticationProvider
4
+
5
+ def initialize(session:nil, params:nil, request_type: type)
6
+ @session = session
7
+ @params = params
8
+ @request_type = request_type
9
+ end
10
+
11
+ def current_user
12
+ @current_user ||= Lanes::User.where(id: @session[:user_id]).first
13
+ end
14
+
15
+ def error_message
16
+ current_user ? "User not found" : error_message_for_access
17
+ end
18
+
19
+ def error_message_for_access
20
+ return "Unable to " + case @request_type
21
+ when 'GET' then "read"
22
+ when 'POST','PATCH','PUT' then "write"
23
+ when 'DELETE' then "delete"
24
+ else
25
+ "perform action"
26
+ end
27
+ end
28
+
29
+ def allowed_access_to?(klass)
30
+ return false if current_user.nil?
31
+ case @request_type
32
+ when 'GET'
33
+ klass.can_read_attributes?(@params,current_user)
34
+ when 'POST','PATCH','PUT'
35
+ klass.can_write_attributes?(@params,current_user)
36
+ when 'DELETE'
37
+ klass.can_delete_attributes?(@params,current_user)
38
+ else
39
+ false
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,290 @@
1
+ # rubocop:disable IndentationWidths
2
+ module Lanes
3
+ module API
4
+
5
+ # The Controller handles querying models
6
+ # using either pre-defined scopes or hash based queries;
7
+ # and also including optional associations with the reply
8
+ #
9
+ # It assigns the following meaning the these parameters.
10
+ # * f: (fields) Include the following fields (usually methods) with the reply
11
+ # * w: (with) Uses the defined scope to query and/or add extra data to the model
12
+ # * q: (query) Query the model using fields and values
13
+ # it is an array of clauses, which can be either forms
14
+ # { field: value }, or { field: { op: 'like', value: 'value%' } }
15
+ # * i: (include) Include associations along with the model in the reply
16
+ # * o: (order) Order by, { field => "ASC|DESC" }
17
+ # * l: (limit) Limit the returned rows to the count
18
+ # * s: (start) Start the query at the given offset (for paging)
19
+ # * df: (data format) Should data be returned as 'object' (default) or 'array'
20
+ # The parameters are deliberately shortened so they can be used in
21
+ # query parameters without blowing the URL up to an unacceptable length
22
+
23
+ class Controller
24
+
25
+ attr_reader :model, :user, :params, :data
26
+
27
+ def initialize(model, authentication, params, data={})
28
+ @user = authentication.current_user
29
+ @model = model
30
+ @params = params
31
+ @data = data
32
+ end
33
+
34
+ def perform_retrieval
35
+ query = build_query
36
+ options = build_reply_options
37
+ options[:total_count] = query.dup.count if should_include_total_count?
38
+ query = add_modifiers_to_query(query)
39
+ Lanes.logger.warn "ID: #{params[:id]}"
40
+ if params[:id]
41
+ query = query.first!
42
+ end
43
+ build_reply(query, :retrieve, options)
44
+ end
45
+
46
+ def perform_creation
47
+ record = model.from_attribute_data(data, user)
48
+ options = build_reply_options.merge(success: record.save)
49
+ build_reply(record, :create, options)
50
+ end
51
+
52
+ def perform_update
53
+ record = build_query.first
54
+ record.set_attribute_data(data, user)
55
+ options = build_reply_options.merge(success: record.save)
56
+ build_reply(record, :update, options)
57
+ end
58
+
59
+ def perform_destroy
60
+ record = model.find(params[:id])
61
+ record.destroy
62
+ build_reply(record, :destroy, {})
63
+ end
64
+
65
+ protected
66
+ # @return [Array<String>] The fields to include in query. May represent either an attribute or a method
67
+ def requested_fields
68
+ [*params[:f]]
69
+ end
70
+ def reply_with_array?
71
+ params[:df] == 'array'
72
+ end
73
+ def query_scopes
74
+ params[:w]
75
+ end
76
+ def query_params
77
+ params[:q]
78
+ end
79
+ def include_associations
80
+ [*params[:i]]
81
+ end
82
+ def sort_order
83
+ params[:o]
84
+ end
85
+ def query_limit_size
86
+ limit = max_query_results_size
87
+ params[:l] ? [ params[:l].to_i, limit ].min : limit
88
+ end
89
+ def query_offset
90
+ params[:s]
91
+ end
92
+
93
+ # json methods
94
+ # constructs a Hash with success, messages, and data keys and
95
+ # populates them appropriately
96
+
97
+ def build_reply(query, type, options)
98
+ success = options[:success].nil? ? true : options[:success]
99
+ json = {}
100
+ if query.is_a?(ActiveRecord::Base) && query.errors.any?
101
+ json[:errors] = {}
102
+ success = false
103
+ query.errors.each{ | attr, message |
104
+ json[:errors][attr] = message
105
+ }
106
+ end
107
+ if options[:total_count]
108
+ json[:total] = options.delete(:total_count)
109
+ end
110
+ json.merge!({
111
+ :success => success,
112
+ :message => options[:messsage] || json_status_str(query, type.to_s.capitalize, success),
113
+ :data => success ? records_for_reply(query, options) : []
114
+ })
115
+ return json
116
+ end
117
+
118
+
119
+ # @return Array<Array> returns either an array of fields
120
+ def records_for_reply(query,options)
121
+ if reply_with_array?
122
+ query.pluck( *requested_fields )
123
+ else
124
+ query.as_json(options)
125
+ end
126
+ end
127
+
128
+ def json_status_str(record, type, success)
129
+ if success
130
+ return type + " succeeded"
131
+ elsif record
132
+ return type + " failed: " + record.errors.full_messages.join("; ")
133
+ else
134
+ return "Record not found"
135
+ end
136
+ end
137
+
138
+ # reply options
139
+
140
+ # Should the result include the total number of available records
141
+ def should_include_total_count?
142
+ params[:l] && params[:s] && ! params[:id]
143
+ end
144
+
145
+ # Extract options that are suitable for use in 'as_json'
146
+ def build_reply_options
147
+ options = {}
148
+ if include_associations.any?
149
+ options[:include] = include_associations.each_with_object({}) do |association, includes|
150
+ includes.merge! build_allowed_associations(association, user)
151
+ end
152
+ end
153
+
154
+ if requested_fields.any?
155
+ options[:methods] = requested_fields.select{|f| model.has_exported_method?(f,user) }
156
+ end
157
+ options
158
+ end
159
+
160
+ def build_allowed_associations(association, user, model_class=self.model)
161
+ includes = {}
162
+ if association.is_a?(Hash)
163
+ association.each do |include_name, sub_associations|
164
+ if model_class.has_exported_association?(include_name, user) &&
165
+ ( reflection = model_class.reflect_on_association( include_name.to_sym ) )
166
+ sub_includes = includes[include_name.to_sym] = {}
167
+ allowed = build_allowed_associations( sub_associations, user, reflection.klass )
168
+ unless allowed.empty?
169
+ sub_includes[:include] ||= []
170
+ sub_includes[:include] << allowed
171
+ end
172
+ end
173
+ end
174
+ elsif association.is_a?(Array)
175
+ association.each do | sub_association |
176
+ if model_class.has_exported_association?(sub_association, user)
177
+ includes.merge! build_allowed_associations( sub_association, user, model_class )
178
+ end
179
+ end
180
+ else
181
+ includes[ association.to_sym ] = {} if model_class.has_exported_association?(association,user)
182
+ end
183
+ includes
184
+ end
185
+
186
+ # query options
187
+
188
+ def build_query(query = model.all)
189
+ if params[:id]
190
+ query = query.where(id: params[:id])
191
+ end
192
+ if params[:nested_attribute]
193
+ query = query.where(params[:nested_attribute])
194
+ end
195
+ if query_scopes.present?
196
+ query = add_scope_to_query(query)
197
+ end
198
+ if query_params.present?
199
+ query = add_params_to_query(query)
200
+ end
201
+ query
202
+ end
203
+
204
+ def add_modifiers_to_query(query)
205
+ query = query.limit(query_limit_size)
206
+ query = query.offset(query_offset.to_i) if query_offset.present?
207
+
208
+ if include_associations.any?
209
+ allowed_includes = include_associations.each_with_object([]) do |desired, results|
210
+ if desired.is_a?(Hash)
211
+ nested = {}
212
+ desired.each do | name, sub_associations |
213
+ nested[name.to_sym] = sub_associations if model.has_exported_association?(name,user)
214
+ end
215
+ results.push(nested) unless nested.empty?
216
+ else
217
+ results.push(desired.to_sym) if model.has_exported_association?(desired,user)
218
+ end
219
+ end
220
+ query = query.includes(allowed_includes) unless allowed_includes.empty?
221
+ end
222
+ if sort_order.present?
223
+ sort_order.each do | fld, dir |
224
+ query = query.order( fld.gsub(/[^\w|^\.]/,'') + ' ' + ( ( 'asc' == dir.downcase ) ? 'ASC' : 'DESC' ) )
225
+ end
226
+ end
227
+ query
228
+
229
+ end
230
+
231
+
232
+ def max_query_results_size
233
+ 250 # should be enough for everybody, amirite?
234
+ end
235
+
236
+ def add_scope_to_query(query)
237
+ query_scopes.each do | name, arg |
238
+ if model.has_exported_scope?(name,user)
239
+ args = [name]
240
+ args.push( arg ) unless arg.blank?
241
+ query = query.send( *args )
242
+ end
243
+ end
244
+ query
245
+ end
246
+
247
+ def add_params_to_query(query)
248
+ query_params.each do | field, value |
249
+ next unless ( field = convert_field_to_arel(field) )
250
+ condition = if value.is_a?(Hash) && value.has_key?('value')
251
+ api_op_string_to_arel_predicate(field, value['op'], value['value'])
252
+ else
253
+ api_op_string_to_arel_predicate(field, nil, value)
254
+ end
255
+ query = query.where(condition)
256
+ end
257
+ query
258
+ end
259
+
260
+ def convert_field_to_arel(field)
261
+ if field.include?('.')
262
+ (table_name, field_name) = field.split('.')
263
+ if model.has_exported_join_table?(table_name, user)
264
+ Arel::Table.new(table_name)[field_name]
265
+ else
266
+ nil
267
+ end
268
+ else
269
+ model.arel_table[field]
270
+ end
271
+ end
272
+
273
+ # complete list: https://github.com/rails/arel/blob/master/lib/arel/predications.rb
274
+ def api_op_string_to_arel_predicate( field, op, value )
275
+ case op
276
+ when 'eq' then field.eq(value)
277
+ when 'ne' then field.not_eq(value)
278
+ when 'lt' then field.lt(value)
279
+ when ( op=='in' && value=~/.*:.*/ ) then field.in( Range.new( *value.split(':') ) )
280
+ when 'gt' then field.gt(value)
281
+ when 'like' then field.matches( value )
282
+ else
283
+ value =~ /%/ ? field.matches( value ) : field.eq( value )
284
+ end
285
+ end
286
+
287
+ end
288
+ end
289
+
290
+ end
@@ -0,0 +1,35 @@
1
+ module Lanes
2
+ module API
3
+
4
+ Root.get '/' do
5
+ content_type 'text/html'
6
+ erb :index
7
+ end
8
+
9
+ Root.get "default-records" do
10
+ { success: true, data: Lanes::API.default_records }
11
+ end
12
+
13
+ Root.post "/user-session.json" do
14
+ wrap_json_reply do
15
+ user = User.where(login: data['login']).first
16
+ if user && user.authenticate(data['password'])
17
+ session[:user_id] = user.id
18
+ { success: true, message: "Login succeeded", data: user.workspace_data }
19
+ else
20
+ { success: false, message: "Login failed", errors: { login: 'failed' }, data: {} }
21
+ end
22
+ end
23
+ end
24
+
25
+ Root.delete "/user-session.json" do
26
+ session.destroy
27
+ { success: true, message: "Logout succeeded", data: {} }
28
+ end
29
+
30
+ Root.build_route User
31
+
32
+
33
+
34
+ end
35
+ end