problem_child 2.0.0 → 2.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e282b0323f0d971146fde3f02147126f0438a506
4
- data.tar.gz: 3b16247f802e2e3f03ce29f8ca6168fe155b9ddd
3
+ metadata.gz: bba9a9faf97164a454765c969947cdd01c0483f8
4
+ data.tar.gz: c6dc44c535d6cd7e83ccad88c078dfa593b82029
5
5
  SHA512:
6
- metadata.gz: f9fea889ff77fccd9640e02f278ca3399a5ca00629773c1b3954f661ccc20af84c3e6505f79cf516904a5a32f1ca568025f80d1e4bb18c85509d271dbbbe4bda
7
- data.tar.gz: 37edf7116f0aaa52c0e0e83dc073b1faf7621d72617d5581920a0308ea342cca047329145940be156324e1a241175da0accdd808d5373f8b8064e80c4b266ffe
6
+ metadata.gz: 9fb22eb689fc603aad6e6ca036bdf258faf5fbaf3ec7b167145f8ae89ad6ef0cb0a341eb36af97fb223a2b77c8873b6942d29f29a0452da04f230ad4fd46b542
7
+ data.tar.gz: cd2d71646e61d08cd32ab36a9aa5e5d65372a2f9338f96c3822423f3c240e73d2625475d04bed3a6b672b66aeb07f6bf8f1befea0f12a55be3aafdd30424f1a0
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Allows authenticated or anonymous users to fill out a standard web form to create GitHub issues.
4
4
 
5
- [![Build Status](https://travis-ci.org/benbalter/problem_child.svg)](https://travis-ci.org/benbalter/problem_child)
5
+ [![Build Status](https://travis-ci.org/benbalter/problem_child.svg)](https://travis-ci.org/benbalter/problem_child) [![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)
6
6
 
7
7
  ## How it works
8
8
 
@@ -14,11 +14,13 @@ Allows authenticated or anonymous users to fill out a standard web form to creat
14
14
 
15
15
  1. Create a `Gemfile` and add `gem "problem_child"`
16
16
  2. Create a `config.ru` file and add the following:
17
- ```ruby
18
- require "problem_child"
19
- run ProblemChild::App
20
- ```
21
- 3. Follow the configuration options below
17
+
18
+ ```ruby
19
+ require "problem_child"
20
+ run ProblemChild::App
21
+ ```
22
+
23
+ Then, follow the configuration options below.
22
24
 
23
25
  ## Requirements
24
26
 
@@ -41,13 +43,19 @@ You must also set **one** of the following:
41
43
  * `GITHUB_ORG_ID` - The GitHub Org ID e.g, `@whitehouse` if you'd like all users to authenticate against a GitHub Org prior to being presented the form
42
44
  * `GITHUB_TEAM_ID` - The numeric Team ID (e.g., 1234) if you'd like all users to authenticate against a GitHub Team prior to being presented the form
43
45
 
46
+ You can also set a variable to enable Google reCAPTCHA support:
47
+
48
+ * `REACAPTCHA_SITE_KEY` - The key created for your reCAPTCHA site via https://www.google.com/recaptcha/admin
49
+
50
+ If set, the Problem child default form will include a bit of JavaScript to test if the reCAPTCHA test was passed before submitting.
51
+
44
52
  *Pro-tip*: When developing locally, you can add these values to a `.env` file in the project root, and they will be automatically read in on load
45
53
 
46
54
  ## Customizing
47
55
 
48
56
  By default, Problem Child will prompt the user with a simple form that contains only the title and body. If you'd like to customize the form, you must do the following:
49
57
 
50
- 1. Create a new folder called `views`
58
+ 1. Create a new directory called `views`
51
59
  2. Create a `layout.erb` and `form.erb`
52
60
  3. Customize both the layout and form as a standard HTML form. Check out [these examples](lib/problem_child/views) to get started.
53
61
  4. Add the following (middle) line to your `config.ru` file:
@@ -73,9 +81,37 @@ or as a checkbox:
73
81
  <input type="checkbox" name="labels[]" value="suggestion" />
74
82
  ```
75
83
 
84
+ *Pro-tip III*: Set the public directory
85
+
86
+ By default Problem child points to an internal public directory which includes jQuery and Twitter Bootstrap. You can add them to your custom layout.erb:
87
+
88
+ ```html
89
+ <link href="/vendor/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
90
+
91
+ <script src="/vender/jquery/dist/jquery.min.js"></script>
92
+ ```
93
+
94
+ However, if you would like to add more files to your form app (e.g., favicon, custom CSS & JS files, etc.), you can redefine where the public directory points:
95
+
96
+ ```ruby
97
+ require "problem_child"
98
+ ProblemChild.views_dir = "/path/to/your/views/directory"
99
+ ProblemChild.public_dir = Rails.public_path
100
+ run ProblemChild::App
101
+ ```
102
+
103
+ Note that you will lose access to the bundled jQuery & Bootstrap libraries and will have to put copies into your new public directory to use them.
104
+
76
105
  ## Creating pull requests
77
106
 
78
- Problem child can also be used to create pull requests. Simply add one or more file inputs to your form. The uploaded files will be committed to a newly created feature branch, and a pull request will be created against the repo's primary branch with the rest of the form content.
107
+ Problem child can also be used to create pull requests. Simply add one or more file inputs to your form. The uploaded files will be committed to a newly created feature branch, and a pull request will be created against the repo's primary branch with the rest of the form content. You'll also want to change the form type to `enctype="multipart/form-data"`.
108
+
109
+ ```html
110
+ <form method="post" enctype="multipart/form-data">
111
+ <input type="file" name="file" />
112
+ <input type="submit" />
113
+ </form>
114
+ ```
79
115
 
80
116
  ## Contributing
81
117
 
@@ -84,3 +120,4 @@ Problem child can also be used to create pull requests. Simply add one or more f
84
120
  3. Commit your changes (`git commit -am 'Add some feature'`)
85
121
  4. Push to the branch (`git push origin my-new-feature`)
86
122
  5. Create a new Pull Request
123
+
data/app.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "Problem Child",
3
+ "description": "Allows authenticated or anonymous users to fill out a standard web form to creat GitHub issues.",
4
+ "repository": "https://github.com/benbalter/problem_child",
5
+ "addons": [
6
+ "heroku-redis:hobby-dev"
7
+ ],
8
+ "env": {
9
+ "GITHUB_CLIENT_ID": {
10
+ "description": "The ID of your GitHub OAuth application, created via https://github.com/settings/applications/new",
11
+ "required": "true"
12
+ },
13
+ "GITHUB_CLIENT_SECRET": {
14
+ "description": "The secret key of your GitHub OAuth application, created via https://github.com/settings/applications/new",
15
+ "required": "true"
16
+ },
17
+ "GITHUB_REPO": {
18
+ "description": "The repository against which to open issues submitted via Problem Child",
19
+ "required": "true"
20
+ },
21
+ "GITHUB_TOKEN": {
22
+ "description": "A personal access token for a bot account with the ability to create an issue in the GITHUB_REPO if you would like all submissions to be anonymous",
23
+ "required": "false"
24
+ },
25
+ "GITHUB_TEAM_ID": {
26
+ "description": "The GitHub Org ID e.g, @whitehouse if you'd like all users to authenticate against a GitHub Org prior to being presented the form",
27
+ "required": "false"
28
+ },
29
+ "GITHUB_ORG_ID": {
30
+ "description": "The numeric Team ID (e.g., 1234) if you'd like all users to authenticate against a GitHub Team prior to being presented the form",
31
+ "required": "false"
32
+ }
33
+ }
34
+ }
@@ -17,6 +17,10 @@ module ProblemChild
17
17
  end
18
18
  end
19
19
 
20
+ def recaptcha
21
+ ENV["RECAPTCHA_SITE_KEY"] unless ENV["RECAPTCHA_SITE_KEY"].nil? || ENV["RECAPTCHA_SITE_KEY"].to_s.empty?
22
+ end
23
+
20
24
  def client
21
25
  @client ||= Octokit::Client.new :access_token => token
22
26
  end
@@ -25,8 +29,16 @@ module ProblemChild
25
29
  halt erb template, :layout => :layout, :locals => locals.merge({ :template => template })
26
30
  end
27
31
 
32
+ def issue_title
33
+ form_data["title"]
34
+ end
35
+
28
36
  def issue_body
29
- form_data.reject { |key, value| key == "title" || value.empty? || key == "labels" || value.is_a?(Hash) }.map { |key,value| "* **#{key.humanize}**: #{value}"}.join("\n")
37
+ form_data.reject { |key, value|
38
+ key == "title" || value.empty? || key == "labels" || value.is_a?(Hash)
39
+ }.except( "g-recaptcha-response" ).map { |key, value|
40
+ "* **#{key.humanize}**: #{value}"
41
+ }.join("\n")
30
42
  end
31
43
 
32
44
  # abstraction to allow cached form data to be used in place of default params
@@ -1,3 +1,3 @@
1
1
  module ProblemChild
2
- VERSION = "2.0.0"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -5,12 +5,22 @@
5
5
  <% end %>
6
6
  </h1>
7
7
 
8
+ <div class="alert alert-warning alert-recaptcha hidden" role="alert">
9
+ Please verify that you are not a robot.
10
+ </div>
11
+
8
12
  <% if issue %>
9
13
  <div class="alert alert-success" role="alert">
10
14
  Your issue was successfully submitted<% if access %> as <a href="http://github.com/<%= repo %>/issues/<%= issue %>"><%= repo %>#<%= issue %></a><% end %>.
11
15
  </div>
12
16
  <% end %>
13
17
 
18
+ <% if flash %>
19
+ <div class="alert alert-info" role="alert">
20
+ <%= flash %>
21
+ </div>
22
+ <% end %>
23
+
14
24
  <form method="post">
15
25
  <div class="form-group">
16
26
  <label for="title">Title</label>
@@ -21,5 +31,9 @@
21
31
  <textarea class="form-control" rows="10" id="body" name="body"></textarea>
22
32
  </div>
23
33
 
34
+ <% if recaptcha.present? %>
35
+ <div class="g-recaptcha" data-sitekey="<%= recaptcha %>"></div>
36
+ <% end %>
37
+
24
38
  <button type="submit" class="btn btn-default">Submit</button>
25
39
  </form>
@@ -16,6 +16,13 @@
16
16
  <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
17
17
  <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
18
18
  <![endif]-->
19
+
20
+ <% if recaptcha.present? %>
21
+ <script src='https://www.google.com/recaptcha/api.js'></script>
22
+ <% end %>
23
+
24
+ <script src='https://www.google.com/recaptcha/api.js'></script>
25
+
19
26
  </head>
20
27
  <body>
21
28
  <div class="container">
@@ -23,5 +30,25 @@
23
30
  <%= yield %>
24
31
 
25
32
  </div>
33
+
34
+ <% if recaptcha.present? %>
35
+ <script src="/vendor/jquery/dist/jquery.min.js"></script>
36
+
37
+ <script>
38
+ $( 'form' ).submit( function( e ) {
39
+ var prevent = false;
40
+
41
+ if ( !grecaptcha.getResponse() ) {
42
+ $( '.alert-recaptcha' ).removeClass( 'hidden' );
43
+ prevent = true;
44
+ }
45
+
46
+ if ( prevent ) {
47
+ e.preventDefault();
48
+ return false;
49
+ }
50
+ } );
51
+ </script>
52
+ <% end %>
26
53
  </body>
27
54
  </html>
data/lib/problem_child.rb CHANGED
@@ -24,6 +24,14 @@ module ProblemChild
24
24
  @views_dir = dir
25
25
  end
26
26
 
27
+ def self.public_dir
28
+ @public_dir ||= File.expand_path "public", ProblemChild.root
29
+ end
30
+
31
+ def self.public_dir=(dir)
32
+ @public_dir = dir
33
+ end
34
+
27
35
  class App < Sinatra::Base
28
36
 
29
37
  include ProblemChild::Helpers
@@ -44,19 +52,26 @@ module ProblemChild
44
52
 
45
53
  set :views, Proc.new { ProblemChild.views_dir }
46
54
  set :root, Proc.new { ProblemChild.root }
47
- set :public_folder, Proc.new { File.expand_path "public", ProblemChild.root }
55
+ set :public_folder, Proc.new { ProblemChild.public_dir }
48
56
 
49
57
  get "/" do
58
+ flash = nil
59
+ issue = nil
60
+ access = false
61
+
50
62
  if session[:form_data]
51
- issue = uploads.empty? ? create_issue : create_pull_request
52
- session[:form_data] = nil
53
- access = repo_access?
63
+ if issue_title.empty?
64
+ flash = 'Please enter a title.'
65
+ else
66
+ issue = uploads.empty? ? create_issue : create_pull_request
67
+ session[:form_data] = nil
68
+ access = repo_access?
69
+ end
54
70
  else
55
- issue = nil
56
- access = false
57
71
  auth!
58
72
  end
59
- halt erb :form, :layout => :layout, :locals => { :repo => repo, :anonymous => anonymous_submissions?, :issue => issue, :access => access }
73
+
74
+ halt erb :form, :layout => :layout, :locals => { :repo => repo, :anonymous => anonymous_submissions?, :flash => flash, :issue => issue, :access => access }
60
75
  end
61
76
 
62
77
  post "/" do
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "rack-ssl-enforcer", "~> 0.2"
24
24
  spec.add_dependency "sinatra_auth_github", "~> 1.0"
25
25
  spec.add_dependency "activesupport", "~> 4.2"
26
- spec.add_dependency "rack", "1.5.2"
26
+ spec.add_dependency "rack", "1.6"
27
27
  spec.add_dependency "redis", "~> 3.2"
28
28
  spec.add_dependency "moneta", "~> 0.8"
29
29
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: problem_child
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Balter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-29 00:00:00.000000000 Z
11
+ date: 2015-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 1.5.2
103
+ version: '1.6'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 1.5.2
110
+ version: '1.6'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: redis
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -249,6 +249,7 @@ files:
249
249
  - Procfile
250
250
  - README.md
251
251
  - Rakefile
252
+ - app.json
252
253
  - bower.json
253
254
  - config.ru
254
255
  - lib/problem_child.rb
@@ -329,7 +330,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
329
330
  version: '0'
330
331
  requirements: []
331
332
  rubyforge_project:
332
- rubygems_version: 2.2.3
333
+ rubygems_version: 2.5.0
333
334
  signing_key:
334
335
  specification_version: 4
335
336
  summary: Allows authenticated or anonymous users to fill out a standard web form to
@@ -339,3 +340,4 @@ test_files:
339
340
  - spec/problem_child_helpers_spec.rb
340
341
  - spec/problem_child_spec.rb
341
342
  - spec/spec_helper.rb
343
+ has_rdoc: