houston-core 0.8.4 → 0.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (225) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +72 -78
  4. data/app/assets/javascripts/houston/app/models/role.coffee +4 -0
  5. data/app/assets/javascripts/houston/app/views/nested_resources.coffee +44 -0
  6. data/app/assets/javascripts/houston/app/views/team_roles_view.coffee +10 -0
  7. data/app/assets/javascripts/houston/application.js +3 -1
  8. data/app/assets/javascripts/houston/core/ajax_helpers.coffee +26 -0
  9. data/app/assets/javascripts/houston/core/app.coffee +0 -45
  10. data/app/assets/javascripts/houston/core/errors.coffee +1 -12
  11. data/app/assets/javascripts/houston/core/handlebars_helpers.coffee +8 -70
  12. data/app/assets/javascripts/houston/core/jquery_extensions.coffee +0 -138
  13. data/app/assets/javascripts/houston/core/timeline_helpers.coffee +44 -0
  14. data/app/assets/javascripts/houston/core/uploader_helpers.coffee +99 -0
  15. data/app/assets/javascripts/houston/vendor.js +26 -9
  16. data/app/assets/stylesheets/houston/application/actions.scss +22 -0
  17. data/app/assets/stylesheets/houston/application/navigation.scss +2 -2
  18. data/app/assets/stylesheets/houston/application/{freight_train.css.scss → nested_resources.scss} +1 -0
  19. data/app/assets/stylesheets/houston/core/alerts.scss +0 -4
  20. data/app/assets/stylesheets/houston/core/timeline.scss +204 -0
  21. data/app/assets/templates/houston/teams/roles/index.hbs +1 -0
  22. data/app/assets/templates/houston/teams/roles/show.hbs +19 -0
  23. data/app/channels/events_channel.rb +1 -1
  24. data/app/concerns/houston/props.rb +3 -2
  25. data/app/controllers/actions_controller.rb +8 -3
  26. data/app/controllers/application_controller.rb +9 -12
  27. data/app/controllers/authorizations_controller.rb +41 -14
  28. data/app/controllers/errors_controller.rb +3 -3
  29. data/app/controllers/project_follows_controller.rb +23 -0
  30. data/app/controllers/project_options_controller.rb +1 -1
  31. data/app/controllers/user_options_controller.rb +1 -1
  32. data/app/helpers/actions_helper.rb +12 -0
  33. data/app/helpers/application_helper.rb +0 -10
  34. data/app/helpers/layout_helper.rb +20 -0
  35. data/app/helpers/markdown_helper.rb +2 -10
  36. data/app/helpers/navigation_helper.rb +5 -5
  37. data/app/helpers/project_helper.rb +6 -0
  38. data/app/helpers/url_helper.rb +4 -4
  39. data/app/helpers/view_extensions_helper.rb +20 -0
  40. data/app/models/action.rb +61 -44
  41. data/app/models/authorization.rb +55 -10
  42. data/app/models/follow.rb +6 -0
  43. data/app/models/persistent_trigger.rb +11 -1
  44. data/app/models/project.rb +5 -27
  45. data/app/models/user.rb +15 -59
  46. data/app/presenters/project_presenter.rb +2 -2
  47. data/app/views/actions/_actions.html.erb +8 -5
  48. data/app/views/actions/index.html.erb +1 -1
  49. data/app/views/actions/running.html.erb +9 -15
  50. data/app/views/actions/show.html.erb +6 -3
  51. data/app/views/actions/unqueued.html.erb +41 -0
  52. data/app/views/authorizations/_form.html.erb +28 -16
  53. data/app/views/authorizations/index.html.erb +9 -4
  54. data/app/views/{oauth/providers/edit.html.erb → authorizations/oauth2_callback.html.erb} +3 -2
  55. data/app/views/devise/sessions/new.html.erb +0 -8
  56. data/app/views/errors/index.html.erb +9 -5
  57. data/app/views/layouts/_navigation.html.erb +9 -0
  58. data/app/views/layouts/application.html.erb +11 -6
  59. data/app/views/layouts/dashboard.html.erb +9 -0
  60. data/app/views/projects/_form.html.erb +7 -18
  61. data/app/views/projects/_header.html.erb +2 -6
  62. data/app/views/projects/index.html.erb +4 -4
  63. data/app/views/teams/_form.html.erb +7 -17
  64. data/app/views/teams/index.html.erb +1 -1
  65. data/app/views/users/_form.html.erb +1 -38
  66. data/config/application.rb +8 -5
  67. data/config/initializers/devise.rb +0 -14
  68. data/config/initializers/secret_token.rb +8 -13
  69. data/config/routes.rb +12 -28
  70. data/db/migrate/20130706141443_drop_deprecated_project_roles.rb +5 -1
  71. data/db/migrate/20170118005958_remove_antecedents_from_versions_of_tickets.rb +1 -1
  72. data/db/migrate/20170130011016_drop_users_environments_subscribed_to.rb +9 -0
  73. data/db/migrate/20170205004452_drop_settings.rb +12 -0
  74. data/db/migrate/20170206002030_drop_extension_hstore.rb +9 -0
  75. data/db/migrate/20170206002732_drop_legacy_columns_from_users.rb +10 -0
  76. data/db/migrate/20170209022159_rename_projects_color_to_color_name.rb +5 -0
  77. data/db/migrate/20170213001453_change_providers_from_models_to_extensions.rb +27 -0
  78. data/db/migrate/20170215012012_add_props_to_authorizations.rb +5 -0
  79. data/db/migrate/20170216041034_add_user_to_persistent_triggers.rb +5 -0
  80. data/db/migrate/20170226201504_create_follows.rb +20 -0
  81. data/db/migrate/20170301014051_drop_name_from_authorizations.rb +9 -0
  82. data/db/migrate/20170307032041_add_created_at_to_actions.rb +11 -0
  83. data/db/migrate/20170307035755_allow_actions_started_at_to_be_null.rb +5 -0
  84. data/db/migrate/20170310024505_replace_authorizations_provider_name_with_type.rb +12 -0
  85. data/db/migrate/20170329030329_drop_consumer_tokens.rb +9 -0
  86. data/db/structure.sql +187 -212
  87. data/houston-core.gemspec +10 -13
  88. data/lib/houston/boot.rb +1 -4
  89. data/lib/houston/boot/actions.rb +24 -21
  90. data/lib/houston/boot/configuration.rb +46 -113
  91. data/lib/houston/boot/extensions.rb +54 -341
  92. data/lib/houston/boot/extensions/deprecated.rb +194 -0
  93. data/lib/houston/boot/extensions/dsl.rb +99 -0
  94. data/lib/houston/boot/extensions/events.rb +81 -0
  95. data/lib/houston/boot/extensions/features.rb +42 -0
  96. data/lib/houston/boot/extensions/layout.rb +70 -0
  97. data/lib/houston/boot/extensions/navigation.rb +42 -0
  98. data/lib/houston/boot/extensions/oauth.rb +62 -0
  99. data/lib/houston/boot/extensions/serializers.rb +29 -0
  100. data/lib/houston/boot/extensions/view.rb +34 -0
  101. data/lib/houston/boot/observer.rb +10 -5
  102. data/{app/models/oauth → lib/houston/boot}/provider.rb +7 -5
  103. data/lib/houston/boot/running_as.rb +0 -5
  104. data/lib/houston/boot/serializer.rb +12 -6
  105. data/lib/houston/boot/{active_record_serializer.rb → serializers/active_record_serializer.rb} +0 -2
  106. data/lib/houston/boot/{readonly_hash_serializer.rb → serializers/readonly_hash_serializer.rb} +0 -2
  107. data/lib/houston/boot/timer.rb +10 -0
  108. data/lib/houston/boot/triggers.rb +27 -8
  109. data/lib/houston/version.rb +1 -1
  110. data/templates/new-instance/.gitignore +0 -4
  111. data/templates/new-instance/config/main.rb +8 -10
  112. data/templates/new-module/test/dummy/houston.rb +1 -0
  113. data/test/acceptance/layout_test.rb +58 -0
  114. data/test/acceptance/updating_props_test.rb +72 -0
  115. data/test/support/config.rb +1 -0
  116. data/test/unit/extensions/events_extension_test.rb +33 -0
  117. data/test/unit/extensions/layout_extension_test.rb +74 -0
  118. data/test/unit/extensions/navigation_extension_test.rb +62 -0
  119. data/test/unit/extensions/oauth_extension_test.rb +91 -0
  120. data/test/unit/extensions/project_features_extension_test.rb +79 -0
  121. data/test/unit/extensions/serializers_extension_test.rb +47 -0
  122. data/test/unit/extensions/view_extension_test.rb +98 -0
  123. data/test/unit/models/actions_test.rb +11 -5
  124. data/test/unit/models/configuration_test.rb +0 -8
  125. data/test/unit/models/observer_test.rb +16 -0
  126. data/test/unit/models/persistent_trigger_test.rb +29 -2
  127. data/test/unit/models/serializer_test.rb +6 -0
  128. data/test/unit/models/timer_test.rb +88 -0
  129. metadata +87 -168
  130. data/app/assets/font/octicons.eot +0 -0
  131. data/app/assets/font/octicons.svg +0 -198
  132. data/app/assets/font/octicons.ttf +0 -0
  133. data/app/assets/font/octicons.woff +0 -0
  134. data/app/assets/font/roboto-black-webfont.eot +0 -0
  135. data/app/assets/font/roboto-black-webfont.svg +0 -675
  136. data/app/assets/font/roboto-black-webfont.ttf +0 -0
  137. data/app/assets/font/roboto-black-webfont.woff +0 -0
  138. data/app/assets/font/roboto-blackitalic-webfont.eot +0 -0
  139. data/app/assets/font/roboto-blackitalic-webfont.svg +0 -677
  140. data/app/assets/font/roboto-blackitalic-webfont.ttf +0 -0
  141. data/app/assets/font/roboto-blackitalic-webfont.woff +0 -0
  142. data/app/assets/font/roboto-bold-webfont.eot +0 -0
  143. data/app/assets/font/roboto-bold-webfont.svg +0 -675
  144. data/app/assets/font/roboto-bold-webfont.ttf +0 -0
  145. data/app/assets/font/roboto-bold-webfont.woff +0 -0
  146. data/app/assets/font/roboto-bolditalic-webfont.eot +0 -0
  147. data/app/assets/font/roboto-bolditalic-webfont.svg +0 -677
  148. data/app/assets/font/roboto-bolditalic-webfont.ttf +0 -0
  149. data/app/assets/font/roboto-bolditalic-webfont.woff +0 -0
  150. data/app/assets/font/roboto-italic-webfont.eot +0 -0
  151. data/app/assets/font/roboto-italic-webfont.svg +0 -668
  152. data/app/assets/font/roboto-italic-webfont.ttf +0 -0
  153. data/app/assets/font/roboto-italic-webfont.woff +0 -0
  154. data/app/assets/font/roboto-light-webfont.eot +0 -0
  155. data/app/assets/font/roboto-light-webfont.svg +0 -666
  156. data/app/assets/font/roboto-light-webfont.ttf +0 -0
  157. data/app/assets/font/roboto-light-webfont.woff +0 -0
  158. data/app/assets/font/roboto-lightitalic-webfont.eot +0 -0
  159. data/app/assets/font/roboto-lightitalic-webfont.svg +0 -668
  160. data/app/assets/font/roboto-lightitalic-webfont.ttf +0 -0
  161. data/app/assets/font/roboto-lightitalic-webfont.woff +0 -0
  162. data/app/assets/font/roboto-medium-webfont.eot +0 -0
  163. data/app/assets/font/roboto-medium-webfont.svg +0 -675
  164. data/app/assets/font/roboto-medium-webfont.ttf +0 -0
  165. data/app/assets/font/roboto-medium-webfont.woff +0 -0
  166. data/app/assets/font/roboto-mediumitalic-webfont.eot +0 -0
  167. data/app/assets/font/roboto-mediumitalic-webfont.svg +0 -677
  168. data/app/assets/font/roboto-mediumitalic-webfont.ttf +0 -0
  169. data/app/assets/font/roboto-mediumitalic-webfont.woff +0 -0
  170. data/app/assets/font/roboto-regular-webfont.eot +0 -0
  171. data/app/assets/font/roboto-regular-webfont.svg +0 -666
  172. data/app/assets/font/roboto-regular-webfont.ttf +0 -0
  173. data/app/assets/font/roboto-regular-webfont.woff +0 -0
  174. data/app/assets/font/roboto-thin-webfont.eot +0 -0
  175. data/app/assets/font/roboto-thin-webfont.svg +0 -666
  176. data/app/assets/font/roboto-thin-webfont.ttf +0 -0
  177. data/app/assets/font/roboto-thin-webfont.woff +0 -0
  178. data/app/assets/font/roboto-thinitalic-webfont.eot +0 -0
  179. data/app/assets/font/roboto-thinitalic-webfont.svg +0 -668
  180. data/app/assets/font/roboto-thinitalic-webfont.ttf +0 -0
  181. data/app/assets/font/roboto-thinitalic-webfont.woff +0 -0
  182. data/app/assets/images/bug-fixed-128.png +0 -0
  183. data/app/assets/images/bug-fixed-32.png +0 -0
  184. data/app/assets/images/bug-fixed-48.png +0 -0
  185. data/app/assets/images/bug-new-128.png +0 -0
  186. data/app/assets/images/bug-new-32.png +0 -0
  187. data/app/assets/images/bug-new-48.png +0 -0
  188. data/app/assets/images/bug-open-32.png +0 -0
  189. data/app/assets/images/bug-zero-128.png +0 -0
  190. data/app/assets/images/bug-zero-48.png +0 -0
  191. data/app/assets/images/drag-grip.png +0 -0
  192. data/app/assets/javascripts/houston/core/burndown_chart.coffee +0 -111
  193. data/app/assets/javascripts/houston/core/stacked_area_graph.coffee +0 -113
  194. data/app/assets/javascripts/houston/core/stacked_bar_graph.coffee +0 -108
  195. data/app/assets/stylesheets/houston/application/project_tiles.scss +0 -26
  196. data/app/assets/stylesheets/houston/application/tips.scss +0 -5
  197. data/app/assets/stylesheets/houston/core/octicons-icons.scss +0 -221
  198. data/app/assets/stylesheets/houston/core/octicons.scss.erb +0 -9
  199. data/app/assets/stylesheets/houston/core/roboto.scss.erb +0 -131
  200. data/app/concerns/historical_weekly_stats.rb +0 -15
  201. data/app/concerns/nosync.rb +0 -21
  202. data/app/controllers/oauth/providers_controller.rb +0 -45
  203. data/app/controllers/project_roles_controller.rb +0 -22
  204. data/app/controllers/settings_controller.rb +0 -14
  205. data/app/controllers/tester_bar_controller.rb +0 -12
  206. data/app/controllers/user_credentials_controller.rb +0 -24
  207. data/app/models/role.rb +0 -33
  208. data/app/models/setting.rb +0 -10
  209. data/app/models/settings.rb +0 -38
  210. data/app/models/slackdown.rb +0 -23
  211. data/app/models/user_credentials.rb +0 -27
  212. data/app/views/errors/_actions.html.erb +0 -17
  213. data/app/views/layouts/_tester_bar.html.erb +0 -6
  214. data/app/views/layouts/minimal.html.erb +0 -50
  215. data/app/views/layouts/naked.html.erb +0 -47
  216. data/app/views/layouts/naked_dashboard.html.erb +0 -50
  217. data/app/views/oauth/providers/_form.html.erb +0 -54
  218. data/app/views/oauth/providers/index.html.erb +0 -41
  219. data/app/views/oauth/providers/new.html.erb +0 -7
  220. data/config/initializers/add_navigation_renderers.rb +0 -5
  221. data/config/initializers/vestal_versions.rb +0 -9
  222. data/db/migrate/20130519163615_create_user_credentials.rb +0 -18
  223. data/lib/houston/boot/events.rb +0 -10
  224. data/lib/tasks/keypair.rake +0 -17
  225. data/vendor/assets/javascripts/jquery.pjax.js +0 -817
data/houston-core.gemspec CHANGED
@@ -28,32 +28,32 @@ Gem::Specification.new do |spec|
28
28
  # --------------------------------
29
29
  spec.add_dependency "activerecord-import"
30
30
  spec.add_dependency "activerecord-pluck_in_batches", "~> 0.2.0"
31
- spec.add_dependency "addressable", "~> 2.3.8"
32
- spec.add_dependency "attentive", ">= 0.3.6"
31
+ spec.add_dependency "addressable", "~> 2.3.8" # <-- 2.5.0 raises "invalid scheme format" for "git@github.com"
32
+ spec.add_dependency "attentive", ">= 0.3.9"
33
33
  spec.add_dependency "browser", "~> 2.3.0"
34
- spec.add_dependency "cancan", "~> 1.6.10" # cancancan
34
+ spec.add_dependency "cancancan", "~> 1.16.0"
35
35
  spec.add_dependency "concurrent-ruby", "~> 1.0.2"
36
36
  spec.add_dependency "devise"
37
37
  spec.add_dependency "devise_invitable"
38
- spec.add_dependency "houston-devise_ldap_authenticatable"
39
38
  spec.add_dependency "faraday", "~> 0.9.2"
40
39
  spec.add_dependency "faraday-http-cache", "~> 1.2.2"
41
40
  spec.add_dependency "faraday-raise-errors", "~> 0.2.0"
42
41
  spec.add_dependency "gemoji", "~> 2.1.0"
43
42
  spec.add_dependency "handlebars_assets", "~> 0.23.0"
44
- spec.add_dependency "neat-rails"
43
+ spec.add_dependency "neat-rails", "~> 0.5.1"
45
44
  spec.add_dependency "nokogiri", "~> 1.7"
46
45
  spec.add_dependency "oauth2"
47
46
  spec.add_dependency "oj", "~> 2.18"
48
47
  spec.add_dependency "openxml-xlsx", ">= 0.2.0"
49
48
  spec.add_dependency "pg_search", "~> 1.0.5"
50
- spec.add_dependency "premailer", "~> 1.8.6"
49
+ spec.add_dependency "premailer", "~> 1.10.0"
51
50
  spec.add_dependency "progressbar", "~> 0.21.0" # for long migrations
52
51
  spec.add_dependency "rack-utf8_sanitizer", "~> 1.3.1"
53
- spec.add_dependency "redcarpet", "~> 3.3.2"
54
- spec.add_dependency "strongbox", "~> 0.7.2" # for encrypting user credentials
55
52
  spec.add_dependency "thor"
56
- spec.add_dependency "houston-vestal_versions"
53
+
54
+ # For parsing Markdown
55
+ spec.add_dependency "kramdown"
56
+ spec.add_dependency "slackdown", ">= 0.2.1"
57
57
 
58
58
  # The Asset Pipeline
59
59
  spec.add_dependency "sass-rails", "~> 5.0"
@@ -61,9 +61,6 @@ Gem::Specification.new do |spec|
61
61
  spec.add_dependency "coffee-rails", "~> 4.1.0"
62
62
 
63
63
  # Houston's background jobs daemon
64
- spec.add_dependency "rufus-scheduler", "~> 3.2.0"
65
-
66
- # Used to edit releases' changes and teams' roles
67
- spec.add_dependency "nested_editor_for"
64
+ spec.add_dependency "rufus-scheduler", "~> 3.3.4"
68
65
 
69
66
  end
data/lib/houston/boot.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  require "houston/boot/configuration"
2
2
  require "houston/boot/running_as"
3
3
  require "houston/boot/daemonize"
4
+ require "houston/boot/serializer"
4
5
  require "houston/boot/extensions"
5
- require "houston/boot/events"
6
-
7
- require "houston/boot/active_record_serializer"
8
- require "houston/boot/readonly_hash_serializer"
9
6
 
10
7
  require "houston/adapters"
11
8
  require "houston/try"
@@ -1,14 +1,14 @@
1
1
  module Houston
2
2
  class Actions
3
- class ExecutionContext < ReadonlyHash
4
- end
5
-
3
+ class UndefinedActionError < ArgumentError; end
4
+ class ExecutionContext < ReadonlyHash; end
6
5
 
7
6
  def initialize
8
7
  @actions = Concurrent::Hash.new
9
8
  end
10
9
 
11
10
 
11
+
12
12
  def names
13
13
  actions.keys
14
14
  end
@@ -25,10 +25,22 @@ module Houston
25
25
  actions[name]
26
26
  end
27
27
 
28
+ def fetch(name)
29
+ actions.fetch(name)
30
+ rescue KeyError
31
+ raise UndefinedActionError, "#{name.inspect} is not defined"
32
+ end
33
+
28
34
  def to_a
29
35
  actions.values
30
36
  end
31
37
 
38
+ def clear
39
+ actions.clear
40
+ end
41
+
42
+
43
+
32
44
  def define(name, required_params=[], &block)
33
45
  raise ArgumentError, "#{name.inspect} is already defined" if exists?(name)
34
46
  redefine(name, required_params, &block)
@@ -45,9 +57,9 @@ module Houston
45
57
  end
46
58
 
47
59
 
60
+
48
61
  def run(name, params={}, options={})
49
- raise ArgumentError, "#{name.inspect} is not defined" unless exists?(name)
50
- action = actions.fetch(name)
62
+ action = fetch(name)
51
63
 
52
64
  unless params.is_a?(Hash)
53
65
  raise ArgumentError, "params must be a Hash" unless params.respond_to?(:to_h)
@@ -58,15 +70,15 @@ module Houston
58
70
  assert_serializable! params
59
71
 
60
72
  Houston.async(options.fetch(:async, true)) do
61
- action.send :run!, params, options
73
+ ::Action.run! name, params, options.fetch(:trigger, "manual")
62
74
  end
63
75
  end
64
76
 
65
77
 
78
+
66
79
  private
67
80
  attr_reader :actions
68
81
 
69
-
70
82
  def assert_required_params!(action, params)
71
83
  action.assert_required_params! params.keys.map(&:to_s)
72
84
  end
@@ -76,6 +88,7 @@ module Houston
76
88
  end
77
89
 
78
90
 
91
+
79
92
  class Action < Struct.new(:name, :required_params, :block)
80
93
  def initialize(name, required_params, block)
81
94
  super name, required_params.map(&:to_s), block
@@ -83,24 +96,14 @@ module Houston
83
96
 
84
97
  def assert_required_params!(params)
85
98
  missing_params = required_params - params
86
- if missing_params.any?
87
- raise Houston::Observer::MissingParamError, "#{missing_params.first.inspect} is a required param of the action #{name.inspect}"
88
- end
99
+ raise Houston::Observer::MissingParamError, "#{missing_params.first.inspect} is a required param of the action #{name.inspect}" if missing_params.any?
89
100
  end
90
101
 
91
- private
92
-
93
- def run!(params, options={})
94
- params = ExecutionContext.new(params)
95
- trigger = options.fetch(:trigger, "manual")
96
-
97
- ::Action.record name, params, trigger do
98
- Rails.logger.info "\e[34m[#{trigger} => #{name}] Running job\e[0m"
99
- params.instance_eval(&block)
100
- end
102
+ def execute(params)
103
+ assert_required_params! params.keys.map(&:to_s)
104
+ ExecutionContext.new(params).instance_eval(&block)
101
105
  end
102
106
  end
103
107
 
104
-
105
108
  end
106
109
  end
@@ -7,6 +7,7 @@ require File.join(root, "lib/houston/boot/triggers")
7
7
  require File.join(root, "lib/houston/boot/observer")
8
8
  require File.join(root, "lib/houston/boot/actions")
9
9
  require File.join(root, "lib/houston/boot/timer")
10
+ require File.join(root, "lib/houston/boot/provider")
10
11
  require File.join(root, "lib/houston/adapters")
11
12
 
12
13
  module Houston
@@ -19,18 +20,18 @@ module_function
19
20
 
20
21
 
21
22
  class Configuration
22
- attr_reader :observer, :actions, :timer
23
+ attr_reader :observer, :actions, :timer, :oauth_providers
23
24
 
24
25
  def initialize
25
26
  @root = Rails.root
27
+ @use_ssl = Rails.env.production?
28
+ @oauth_providers = []
26
29
  @roles = Hash.new { |hash, key| hash[key] = [] }
27
30
  @roles["Team Owner"].push(Proc.new do |team|
28
31
  can :manage, team
29
32
  can :manage, Project, team_id: team.id
30
33
  end)
31
34
  @modules = []
32
- @authentication_strategy = :database
33
- @authentication_strategy_configuration = {}
34
35
  end
35
36
 
36
37
  def triggers
@@ -117,6 +118,20 @@ module_function
117
118
  @host ||= nil
118
119
  end
119
120
 
121
+ def use_ssl(*args)
122
+ @use_ssl = args.first if args.any?
123
+ @use_ssl
124
+ end
125
+
126
+ def use_ssl?
127
+ @use_ssl
128
+ end
129
+
130
+ def secret_key_base(*args)
131
+ return Houston::Application.config.secret_key_base if args.none?
132
+ Houston::Application.config.secret_key_base = args.first
133
+ end
134
+
120
135
  def time_zone(*args)
121
136
  return Rails.application.config.time_zone if args.none?
122
137
  Rails.application.config.time_zone = args.first
@@ -150,15 +165,6 @@ module_function
150
165
  @password_length ||= 8..128
151
166
  end
152
167
 
153
- def passphrase(*args)
154
- @passphrase = args.first if args.any?
155
- @passphrase ||= nil
156
- end
157
-
158
- def keypair
159
- root.join("config", "keypair.pem")
160
- end
161
-
162
168
  def parallelization(*args)
163
169
  @parallelization = args.first if args.any?
164
170
  @parallelization ||= :off
@@ -178,6 +184,19 @@ module_function
178
184
  @s3 ||= {}
179
185
  end
180
186
 
187
+ def oauth(provider_name, &block)
188
+ settings = HashDsl.hash_from_block(block)
189
+ provider = Houston.oauth.get_provider(provider_name)
190
+
191
+ raise ArgumentError, "Provider must define a client_id" if settings[:client_id].blank?
192
+ raise ArgumentError, "Provider must define a client_secret" if settings[:client_secret].blank?
193
+
194
+ provider.client_id = settings[:client_id]
195
+ provider.client_secret = settings[:client_secret]
196
+
197
+ @oauth_providers << provider_name.to_s
198
+ end
199
+
181
200
  def project_categories(*args)
182
201
  @project_categories = args if args.any?
183
202
  @project_categories ||= []
@@ -185,21 +204,21 @@ module_function
185
204
 
186
205
  def navigation(*args)
187
206
  @navigation = args if args.any?
188
- return Houston.available_navigation_renderers unless @navigation
189
- @navigation & Houston.available_navigation_renderers
207
+ return Houston.navigation.slugs unless @navigation
208
+ @navigation & Houston.navigation.slugs
190
209
  end
191
210
 
192
211
  def project_features(*args)
193
212
  @project_features = args if args.any?
194
- return Houston.available_project_features unless @project_features
195
- @project_features & Houston.available_project_features
213
+ return Houston.project_features.all unless @project_features
214
+ @project_features & Houston.project_features.all
196
215
  end
197
216
 
198
217
 
199
218
 
200
219
  def project_colors(*args)
201
- new_hash = Hash.new(ColorValue.new("505050"))
202
- @project_colors = args.first.each_with_object(new_hash) { |(key, hex), hash| hash[key] = ColorValue.new(hex) } if args.any?
220
+ new_hash = Hash.new(ColorValue.new("default", "505050"))
221
+ @project_colors = args.first.each_with_object(new_hash) { |(key, hex), hash| hash[key] = ColorValue.new(key, hex) } if args.any?
203
222
  @project_colors ||= new_hash
204
223
  end
205
224
 
@@ -220,50 +239,6 @@ module_function
220
239
 
221
240
 
222
241
 
223
- # Authentication options
224
-
225
- def authentication_strategy(strategy=nil, &block)
226
- @authentication_strategy = strategy if strategy
227
- if block_given?
228
- @authentication_strategy_configuration = HashDsl.hash_from_block(block)
229
-
230
- if authentication_strategy == :ldap
231
- %i{host port base field username_builder}.each do |required_field|
232
- next if @authentication_strategy_configuration.key?(required_field)
233
- raise "#{required_field} is a required field for :ldap authentication"
234
- end
235
- end
236
- end
237
-
238
- @authentication_strategy
239
- end
240
- attr_reader :authentication_strategy_configuration
241
-
242
- def devise_configuration
243
- # Include default devise modules. Others available are:
244
- # :registerable,
245
- # :encryptable,
246
- # :confirmable,
247
- # :lockable,
248
- # :timeoutable,
249
- # :omniauthable
250
-
251
- configuration = [:database_authenticatable]
252
- unless Rails.env.test? # <-- !todo: control when custom strategies are employed in the test suite
253
- configuration << :ldap_authenticatable if authentication_strategy == :ldap
254
- end
255
- configuration.concat [
256
- :recoverable,
257
- :rememberable,
258
- :trackable,
259
- :validatable,
260
- :invitable ]
261
- end
262
-
263
-
264
-
265
-
266
-
267
242
  # Permissions
268
243
 
269
244
  def abilities(&block)
@@ -327,7 +302,7 @@ module_function
327
302
 
328
303
  def on(*args, &block)
329
304
  event_name, action_name = extract_trigger_and_action!(args)
330
- event = Houston.get_registered_event(event_name)
305
+ event = Houston.events[event_name]
331
306
 
332
307
  unless event
333
308
  puts "\e[31mUnregistered event: \e[1m#{event_name}\e[0;90m\n#{caller[0]}\e[0m\n\n"
@@ -341,53 +316,10 @@ module_function
341
316
  action
342
317
  end
343
318
 
344
- # DEPRECATED
345
- def at(*args, &block)
346
- time, action_name = extract_trigger_and_action!(args)
347
- action = assert_action! action_name, &block
348
- action.assert_required_params! []
349
-
350
- # Passing options to Houston.config.at is deprecated
351
- # -------------------------------------------------------------- #
352
- if args.first.is_a?(Hash)
353
- options = args.first
354
- if days_of_the_week = options.delete(:every)
355
- Houston.deprecation_notice "Instead of passing every: #{days_of_the_week.inspect} to Houston.config.at, use Houston.config.at [#{days_of_the_week.inspect}, #{time}], ..."
356
- time = [days_of_the_week, time]
357
- end
358
- options.keys.each do |key|
359
- Houston.deprecation_notice "#{key.inspect} is an unknown option for Houston.config.at. In the next version of houston-core, Houston.config.at will no longer accept options"
360
- end
361
- end
362
- # -------------------------------------------------------------- #
363
-
364
- # Houston.config.at is deprecated
365
- # -------------------------------------------------------------- #
366
- value = time
367
- wdays, time = value.is_a?(Array) ? value : [:day, value]
368
- interval = "#{wdays} at #{time}"
369
- Houston.deprecation_notice "Houston.config.at(#{value.inspect}) is deprecated; use Houston.config.every(#{interval.inspect}) instead"
370
- # -------------------------------------------------------------- #
371
-
372
- triggers.every interval, action_name
373
- action
374
- end
375
-
376
319
  def every(*args, &block)
377
320
  interval, action_name = extract_trigger_and_action!(args)
378
321
  action = assert_action! action_name, &block
379
322
  action.assert_required_params! []
380
-
381
- # Passing options to Houston.config.every is deprecated
382
- # -------------------------------------------------------------- #
383
- if args.first.is_a?(Hash)
384
- options = args.first
385
- options.keys.each do |key|
386
- Houston.deprecation_notice "#{key.inspect} is an unknown option for Houston.config.at. In the next version of houston-core, Houston.config.at will no longer accept options"
387
- end
388
- end
389
- # -------------------------------------------------------------- #
390
-
391
323
  triggers.every interval, action_name
392
324
  action
393
325
  end
@@ -398,11 +330,6 @@ module_function
398
330
  raise ArgumentError, "Unrecognized trigger: #{args.inspect}"
399
331
  end
400
332
  return args.shift(2) if args.length >= 2
401
- if args.length == 1
402
- method_name = caller[0][/in `(.*)'/, 1]
403
- Houston.deprecation_notice "<b>Houston.config.#{method_name}(#{args[0].inspect})</b> does not specify an action name\nIn a future version of Houston <b>Houston.config.#{method_name}(#{args[0]} => \"do-something\")</b> will be required", 2
404
- return [args[0], "#{args[0]}:#{SecureRandom.hex}"]
405
- end
406
333
  raise NotImplementedError, "I haven't been programmed to extract trigger and action_name from #{args.inspect}"
407
334
  end
408
335
 
@@ -490,14 +417,20 @@ module_function
490
417
 
491
418
 
492
419
  class ColorValue
420
+ attr_reader :name
493
421
  attr_reader :hex
494
422
 
495
- def initialize(hex)
423
+ def initialize(name, hex)
424
+ @name = name
496
425
  @hex = hex
497
426
  end
498
427
 
428
+ def as_json(options={})
429
+ name
430
+ end
431
+
499
432
  def to_s
500
- @hex
433
+ name
501
434
  end
502
435
 
503
436
  def rgb
@@ -1,378 +1,91 @@
1
- require "houston/boot/serializer"
1
+ require "houston/boot/extensions/events"
2
+ require "houston/boot/extensions/layout"
3
+ require "houston/boot/extensions/navigation"
4
+ require "houston/boot/extensions/oauth"
5
+ require "houston/boot/extensions/features"
6
+ require "houston/boot/extensions/serializers"
7
+ require "houston/boot/extensions/view"
8
+ require "houston/boot/extensions/deprecated"
9
+ require "houston/boot/serializers/active_record_serializer"
10
+ require "houston/boot/serializers/readonly_hash_serializer"
2
11
 
3
12
 
4
13
  module Houston
5
14
  module Extensions
6
- attr_reader :events, :serializers
15
+ include Houston::Extensions::Deprecated
7
16
 
8
-
9
-
10
- def available_navigation_renderers
11
- @navigation_renderers.keys
12
- end
13
-
14
- def get_navigation_renderer(name)
15
- @navigation_renderers.fetch(name)
16
- end
17
-
18
- def add_navigation_renderer(slug, &block)
19
- dsl = FeatureDsl.new(GlobalFeature.new)
20
- dsl.instance_eval(&block)
21
- feature = dsl.feature
22
- feature.slug = slug
23
- raise ArgumentError, "Renderer must supply name, but #{slug.inspect} doesn't" unless feature.name
24
- raise ArgumentError, "Renderer must supply path lambda, but #{slug.inspect} doesn't" unless feature.path_block
25
-
26
- @navigation_renderers[slug] = feature
27
- end
28
-
29
-
30
-
31
-
32
- def available_project_features
33
- @available_project_features.keys
34
- end
35
-
36
- def get_project_feature(slug)
37
- @available_project_features.fetch(slug)
38
- end
39
-
40
- def add_project_feature(slug, &block)
41
- dsl = FeatureDsl.new(ProjectFeature.new)
42
- dsl.instance_eval(&block)
43
- feature = dsl.feature
44
- feature.slug = slug
45
- raise ArgumentError, "Project Feature must supply name, but #{slug.inspect} doesn't" unless feature.name
46
- raise ArgumentError, "Project Feature must supply path lambda, but #{slug.inspect} doesn't" unless feature.path_block
47
-
48
- @available_project_features[slug] = feature
49
- end
50
-
51
-
52
-
53
- def add_user_option(slug, &block)
54
- dsl = FormBuilderDsl.new
55
- dsl.instance_eval(&block)
56
- form = dsl.form
57
- form.slug = slug
58
-
59
- @user_options[slug] = form
60
- end
61
-
62
- def user_options
63
- @user_options.values
64
- end
65
-
66
-
67
-
68
- def add_project_option(slug, &block)
69
- dsl = FormBuilderDsl.new
70
- dsl.instance_eval(&block)
71
- form = dsl.form
72
- form.slug = slug
73
-
74
- @project_options[slug] = form
17
+ def events
18
+ return @events if defined?(@events)
19
+ @events = Houston::Extensions::Events.new
75
20
  end
76
21
 
77
- def project_options
78
- @project_options.values
22
+ def layout
23
+ return @layout if defined?(@layout)
24
+ @layout = Houston::Extensions::Layout.new
79
25
  end
80
26
 
81
-
82
-
83
- def add_project_header_command(slug, &block)
84
- dsl = ProjectBannerFeatureDsl.new(ProjectBannerFeature.new)
85
- dsl.instance_eval(&block)
86
- feature = dsl.feature
87
- feature.slug = slug
88
-
89
- @project_header_commands[slug] = feature
27
+ def navigation
28
+ return @navigation if defined?(@navigation)
29
+ @navigation = Houston::Extensions::Navigation.new
90
30
  end
91
31
 
92
- def project_header_commands
93
- @project_header_commands.values
32
+ def oauth
33
+ return @oauth if defined?(@oauth)
34
+ @oauth = Houston::Extensions::Oauth.new
94
35
  end
95
36
 
96
-
97
-
98
- def add_project_column(slug, &block)
99
- dsl = ProjectColumnDsl.new(ProjectColumn.new)
100
- dsl.instance_eval(&block)
101
- feature = dsl.feature
102
- feature.slug = slug
103
-
104
- @project_columns[slug] = feature
105
- end
106
-
107
- def project_columns
108
- @project_columns.values
37
+ def project_features
38
+ return @project_features if defined?(@project_features)
39
+ @project_features = Houston::Extensions::Features.new
109
40
  end
110
41
 
111
-
112
-
113
- def registered_event?(event_name)
114
- events.any? { |event| event.matches? event_name }
42
+ def serializers
43
+ return @serializers if defined?(@serializers)
44
+ @serializers = Houston::Extensions::Serializers.new
115
45
  end
116
46
 
117
- def get_registered_event(event_name)
118
- events.find { |event| event.matches? event_name }
47
+ def view
48
+ return @view if defined?(@view)
49
+ @view = Houston::Extensions::Views.new
119
50
  end
120
51
 
121
- def register_event(name, description)
122
- events.push Event.new(name, description)
123
- end
124
52
 
125
53
  def register_events(&block)
126
- dsl = RegisterEventsDsl.new
127
- hash = dsl.instance_eval(&block)
128
- hash.each do |name, description|
129
- register_event(name, description.to_h)
130
- end
54
+ events.register(&block)
131
55
  end
132
56
 
133
-
134
-
135
57
  def add_serializer(serializer)
136
- [:applies_to?, :pack].each do |method|
137
- next if serializer.respond_to?(method)
138
- raise ArgumentError, "`serializer` must respond to `#{method}`"
139
- end
140
-
141
- @serializers.push serializer
142
- end
143
-
144
-
145
-
146
- def accept_credentials_for(service, &test_connection_proc)
147
- @credentials_services[service] = test_connection_proc
148
- end
149
-
150
- def user_credentials_support_services
151
- @credentials_services.values
152
- end
153
-
154
- def test_connection_to(credentials)
155
- login = credentials.login
156
- password = credentials.password.decrypt(Houston.config.passphrase)
157
- errors = credentials.errors
158
- @credentials_services[credentials.service].call(login, password, errors)
159
- end
160
-
161
-
162
-
163
- private
164
-
165
- class GlobalFeature
166
- attr_accessor :name, :slug, :icon, :path_block, :ability_block
167
-
168
- def path
169
- path_block.call
170
- end
171
-
172
- def permitted?(ability)
173
- return true if ability_block.nil?
174
- ability_block.call ability
175
- end
176
- end
177
-
178
- class ProjectFeature < GlobalFeature
179
- attr_accessor :fields
180
-
181
- def initialize
182
- self.fields = []
183
- end
184
-
185
- def project_path(project)
186
- path_block.call project
187
- end
188
- alias :path :project_path
189
-
190
- def permitted?(ability, project)
191
- return true if ability_block.nil?
192
- ability_block.call ability, project
193
- end
194
- end
195
-
196
- class FeatureDsl
197
- attr_reader :feature
198
-
199
- def initialize(feature)
200
- @feature = feature
201
- end
202
-
203
- def name(value)
204
- feature.name = value
205
- end
206
-
207
- def icon(value)
208
- Houston.deprecation_notice "The icon option will be removed in Houston 0.9.0"
209
- feature.icon = value
210
- end
211
-
212
- def path(&block)
213
- feature.path_block = block
214
- end
215
-
216
- def ability(&block)
217
- feature.ability_block = block
218
- end
219
-
220
- def field(slug, &block)
221
- dsl = FormBuilderDsl.new
222
- dsl.instance_eval(&block)
223
- form = dsl.form
224
- form.slug = slug
225
- feature.fields.push form
226
- end
227
- end
228
-
229
- class ProjectFeatureForm
230
- attr_accessor :slug, :name, :render_block
231
-
232
- def render(view, f)
233
- view.instance_exec(f, &render_block).html_safe
234
- end
235
- end
236
-
237
- class FormBuilderDsl
238
- attr_reader :form
239
-
240
- def initialize
241
- @form = ProjectFeatureForm.new
242
- end
243
-
244
- def name(value)
245
- form.name = value
246
- end
247
-
248
- def html(&block)
249
- form.render_block = block
250
- end
251
- end
252
-
253
- class ProjectBannerFeature
254
- attr_accessor :partial
255
- attr_accessor :ability_block
256
- attr_accessor :slug
257
-
258
- def permitted?(ability, project)
259
- return true if ability_block.nil?
260
- ability_block.call ability, project
261
- end
262
- end
263
-
264
- class ProjectBannerFeatureDsl
265
- attr_reader :feature
266
-
267
- def initialize(feature)
268
- @feature = feature
269
- end
270
-
271
- def partial(value)
272
- feature.partial = value
273
- end
274
-
275
- def ability(&block)
276
- feature.ability_block = block
277
- end
278
- end
279
-
280
- class ProjectColumn
281
- attr_accessor :html_block
282
- attr_accessor :ability_block
283
- attr_accessor :slug
284
- attr_accessor :name
285
-
286
- def render(project)
287
- html_block.call project
288
- end
289
-
290
- def permitted?(ability)
291
- return true if ability_block.nil?
292
- ability_block.call ability
293
- end
58
+ serializers.add(serializer)
294
59
  end
295
60
 
296
- class ProjectColumnDsl
297
- attr_reader :feature
298
-
299
- def initialize(feature)
300
- @feature = feature
301
- end
302
-
303
- def name(value)
304
- feature.name = value
305
- end
306
-
307
- def html(&block)
308
- feature.html_block = block
309
- end
310
-
311
- def ability(&block)
312
- feature.ability_block = block
313
- end
314
- end
315
-
316
- class RegisterEventsDsl
317
- def params(*params)
318
- RegisterEventDsl.new.params(*params)
319
- end
320
-
321
- def description(value)
322
- RegisterEventDsl.new.description(value)
323
- end
324
- alias :desc :description
325
- end
326
-
327
- class RegisterEventDsl
328
- def initialize
329
- @hash = {}
330
- end
61
+ end
331
62
 
332
- def params(*params)
333
- @hash[:params] = params
334
- self
335
- end
336
63
 
337
- def description(value)
338
- @hash[:description] = value
339
- self
340
- end
341
- alias :desc :description
342
64
 
343
- def to_h
344
- @hash
345
- end
346
- end
65
+ extend Extensions
347
66
 
348
- class Event
349
- attr_reader :name, :description, :params
67
+ view["projects"].has :Table
68
+ view["users"].has :Table
69
+ view["edit_project"].has :Form
70
+ view["edit_user"].has :Form
350
71
 
351
- def initialize(name, options)
352
- @name = name
353
- @description = options.fetch(:description)
354
- @params = options.fetch(:params, [])
355
- @matcher = Regexp.new("\\A#{name.gsub /\{([^:}]+)\}/, "(?<\\1>[^:]+)"}\\z")
356
- end
72
+ project_features
73
+ .add(:settings) { |project| Houston::Application.routes.url_helpers.edit_project_path(project) }
74
+ .ability { |project| can?(:update, project) }
357
75
 
358
- def matches?(event_name)
359
- @matcher === event_name
360
- end
361
- end
76
+ register_events {{
77
+ "daemon:{type}:start" => desc("Daemon {type} has started"),
78
+ "daemon:{type}:restart" => desc("Daemon {type} has restarted"),
79
+ "daemon:{type}:stop" => desc("Daemon {type} has stopped"),
362
80
 
363
- end
81
+ "hooks:{type}" => params("params").desc("/hooks/{type} was invoked"),
82
+ "hooks:project:{type}" => params("project", "params").desc("/hooks/project/:slug/{type} was invoked"),
364
83
 
84
+ "authorization:grant" => params("authorization").desc("Authorization was granted"),
85
+ "authorization:revoke" => params("authorization").desc("Authorization was revoked")
86
+ }}
365
87
 
88
+ serializers << Houston::ActiveRecordSerializer.new
89
+ serializers << Houston::ReadonlyHashSerializer.new
366
90
 
367
- @navigation_renderers = {}
368
- @available_project_features = {}
369
- @user_options = {}
370
- @project_options = {}
371
- @project_columns = {}
372
- @project_header_commands = {}
373
- @events = []
374
- @event_matchers = []
375
- @serializers = []
376
- @credentials_services = {}
377
- extend Houston::Extensions
378
91
  end