problem_child 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 89ffeb15ad0f753317aaa3f2f19dd64e94972443
4
- data.tar.gz: 179d480027eed558ae74e810c1c700efc4ee414f
3
+ metadata.gz: 57eaad2eea8f2a2c3531c5e454eba665a65197e1
4
+ data.tar.gz: 97958f47536e64388b3fb9862dcfdeeb235b66fc
5
5
  SHA512:
6
- metadata.gz: 223bef3364e7c6d68ddea4a314cb538a1bb378c502ab1725a06d5895b86e785af4bd52bdbb11bb8fa17db5291039c711a18da78ff8452989c84b56c4c086a406
7
- data.tar.gz: cf47ab4bbf372e5280382e787f00c17bf87d0b60fde4dd2046737121fb3ec148709dc7d6b26ca79d172ec0ed31876a2d2b76f9534079d9054ba1b3c345beff36
6
+ metadata.gz: ff66d7eadeff9293a116e1ec1472d259670871ee7cbd2ff761046fc0e7318999504935b95c3fd05f90946fb62e1aa702a2e9098a1c4dd1708cca9fc208eb2b89
7
+ data.tar.gz: bcbdb1d8839888435faa0a78352682526542eb06e91e1409637fb09b60742cb763b8562506cf8d75f83c52df131f22c3155b7062689d3c9e54e80b4e7add05d8
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ script: "./script/cibuild"
3
+
4
+ rvm:
5
+ - 2.1
6
+
7
+ sudo: false
8
+ cache: bundler
9
+
10
+ env:
11
+ global:
12
+ GITHUB_CLIENT_ID: "1234"
13
+ GITHUB_CLIENT_SECRET: "1234"
data/README.md CHANGED
@@ -2,6 +2,8 @@
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)
6
+
5
7
  ## How it works
6
8
 
7
9
  1. You create a standard HTML form, defining what fields you'd like a given authenticated or anonymous user to fill out
data/Rakefile CHANGED
@@ -1,8 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
- require 'rake/testtask'
2
+ require 'rspec/core/rake_task'
3
3
 
4
- Rake::TestTask.new(:test) do |test|
5
- test.libs << 'lib' << 'test'
6
- test.pattern = 'test/**/test_problem_child*.rb'
7
- test.verbose = true
4
+ desc "Run specs"
5
+ RSpec::Core::RakeTask.new do |t|
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ t.rspec_opts = ["--order", "rand", "--color"]
8
8
  end
@@ -0,0 +1,54 @@
1
+ module ProblemChild
2
+ module Helpers
3
+
4
+ def repo
5
+ ENV["GITHUB_REPO"]
6
+ end
7
+
8
+ def anonymous_submissions?
9
+ !!(ENV["GITHUB_TOKEN"] && !ENV["GITHUB_TOKEN"].to_s.empty?)
10
+ end
11
+
12
+ def token
13
+ if anonymous_submissions?
14
+ ENV["GITHUB_TOKEN"]
15
+ elsif !github_user.nil?
16
+ github_user.token
17
+ end
18
+ end
19
+
20
+ def client
21
+ @client ||= Octokit::Client.new :access_token => token
22
+ end
23
+
24
+ def render_template(template, locals={})
25
+ halt erb template, :layout => :layout, :locals => locals.merge({ :template => template })
26
+ end
27
+
28
+ def issue_body
29
+ form_data.reject { |key, value| key == "title" || value.empty? }.map { |key,value| "* **#{key.humanize}**: #{value}"}.join("\n")
30
+ end
31
+
32
+ # abstraction to allow cached form data to be used in place of default params
33
+ def form_data
34
+ session["form_data"].nil? ? params : JSON.parse(session["form_data"])
35
+ end
36
+
37
+ def create_issue
38
+ client.create_issue(repo, form_data["title"], issue_body)
39
+ end
40
+
41
+ def auth!
42
+ if anonymous_submissions?
43
+ true
44
+ elsif ENV['GITHUB_TEAM_ID']
45
+ github_team_authenticate!(ENV['GITHUB_TEAM_ID'])
46
+ elsif ENV['GITHUB_ORG_ID']
47
+ github_organization_authenticate!(ENV['GITHUB_ORG_ID'])
48
+ else
49
+ raise "Must define GITHUB_TEAM_ID, GITHUB_ORG_ID, OR GITHUB_TOKEN"
50
+ halt 401
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module ProblemChild
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/problem_child.rb CHANGED
@@ -6,6 +6,7 @@ require 'json'
6
6
  require 'active_support'
7
7
  require 'active_support/core_ext/string'
8
8
  require "problem_child/version"
9
+ require "problem_child/helpers"
9
10
 
10
11
  module ProblemChild
11
12
 
@@ -23,16 +24,15 @@ module ProblemChild
23
24
 
24
25
  class App < Sinatra::Base
25
26
 
26
- enable :sessions
27
+ include ProblemChild::Helpers
27
28
 
28
29
  set :github_options, {
29
- :scopes => "repo",
30
- :secret => ENV['GITHUB_CLIENT_SECRET'],
31
- :client_id => ENV['GITHUB_CLIENT_ID'],
30
+ :scopes => "repo"
32
31
  }
33
32
 
34
33
  register Sinatra::Auth::Github
35
34
 
35
+ enable :sessions
36
36
  use Rack::Session::Cookie, {
37
37
  :http_only => true,
38
38
  :secret => SecureRandom.hex
@@ -44,63 +44,9 @@ module ProblemChild
44
44
  end
45
45
 
46
46
  set :views, Proc.new { ProblemChild.views_dir }
47
- set :root, Proc.new { ProblemChild.root }
47
+ set :root, Proc.new { ProblemChild.root }
48
48
  set :public_folder, Proc.new { File.expand_path "public", ProblemChild.root }
49
49
 
50
- def repo
51
- ENV["GITHUB_REPO"]
52
- end
53
-
54
- def user
55
- env['warden'].user unless env['warden'].nil?
56
- end
57
-
58
- def anonymous_submissions?
59
- ENV["GITHUB_TOKEN"] && !ENV["GITHUB_TOKEN"].empty?
60
- end
61
-
62
- def token
63
- if anonymous_submissions?
64
- ENV["GITHUB_TOKEN"]
65
- elsif !user.nil?
66
- user.token
67
- end
68
- end
69
-
70
- def client
71
- @client ||= Octokit::Client.new :access_token => token
72
- end
73
-
74
- def render_template(template, locals={})
75
- halt erb template, :layout => :layout, :locals => locals.merge({ :template => template })
76
- end
77
-
78
- def issue_body
79
- form_data.reject { |key, value| key == "title" || value.empty? }.map { |key,value| "* **#{key.humanize}**: #{value}"}.join("\n")
80
- end
81
-
82
- # abstraction to allow cached form data to be used in place of default params
83
- def form_data
84
- session["form_data"].nil? ? params : JSON.parse(session["form_data"])
85
- end
86
-
87
- def create_issue
88
- client.create_issue(repo, form_data["title"], issue_body)
89
- end
90
-
91
- def auth!
92
- if anonymous_submissions?
93
- true
94
- elsif ENV['GITHUB_TEAM_ID']
95
- github_team_authenticate!(ENV['GITHUB_TEAM_ID'])
96
- elsif ENV['GITHUB_ORG_ID']
97
- github_organization_authenticate!(ENV['GITHUB_ORG_ID'])
98
- else
99
- raise "Must define GITHUB_TEAM_ID, GITHUB_ORG_ID, OR GITHUB_TOKEN"
100
- halt 401
101
- end
102
- end
103
-
104
50
  get "/" do
105
51
  if session[:form_data]
106
52
  flash = :success if create_issue
@@ -113,12 +59,9 @@ module ProblemChild
113
59
  end
114
60
 
115
61
  post "/" do
116
- if anonymous_submissions?
117
- create_issue
118
- else
119
- session[:form_data] = params.to_json
120
- auth!
121
- end
62
+ session[:form_data] = params.to_json
63
+ auth! unless anonymous_submissions?
64
+ halt redirect "/"
122
65
  end
123
66
  end
124
67
  end
@@ -25,6 +25,9 @@ Gem::Specification.new do |spec|
25
25
  spec.add_dependency "activesupport", "~> 4.2"
26
26
  spec.add_dependency "rack", "1.5.2"
27
27
 
28
+ spec.add_development_dependency "rspec", "~> 3.1"
29
+ spec.add_development_dependency "rack-test", "~> 0.6"
30
+ spec.add_development_dependency "webmock", "~> 1.2 "
28
31
  spec.add_development_dependency "foreman", "~> 0.77"
29
32
  spec.add_development_dependency "bundler", "~> 1.6"
30
33
  spec.add_development_dependency "rake", "~> 10.4"
data/script/cibuild ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+ bundle exec rake spec
5
+ bundle exec gem build problem_child.gemspec
@@ -0,0 +1,93 @@
1
+ require "spec_helper"
2
+
3
+ describe "ProblemChild::Helpers" do
4
+
5
+ class TestHelper
6
+ include ProblemChild::Helpers
7
+
8
+ attr_accessor :session, :params
9
+
10
+ def initialize(path=nil)
11
+ @path = path
12
+ end
13
+
14
+ def request
15
+ Rack::Request.new("PATH_INFO" => @path)
16
+ end
17
+ end
18
+
19
+ before(:each) do
20
+ @helper = TestHelper.new
21
+ @helper.session = {}
22
+ @helper.params = {}
23
+ end
24
+
25
+ it "knows the github repo" do
26
+ with_env "GITHUB_REPO", "foo/bar" do
27
+ expect(@helper.repo).to eql("foo/bar")
28
+ end
29
+ end
30
+
31
+ it "knows to allow anonymous submisssions when a token is passed" do
32
+ with_env "GITHUB_TOKEN", "asdf" do
33
+ expect(@helper.anonymous_submissions?).to be(true)
34
+ end
35
+ end
36
+
37
+ it "knows not to allow anonymous submisssions when no token is passed" do
38
+ with_env "GITHUB_TOKEN", "" do
39
+ expect(@helper.anonymous_submissions?).to be(false)
40
+ end
41
+
42
+ with_env "GITHUB_TOKEN", nil do
43
+ expect(@helper.anonymous_submissions?).to be(false)
44
+ end
45
+ end
46
+
47
+ it "uses a token if passed" do
48
+ with_env "GITHUB_TOKEN", "asdf" do
49
+ expect(@helper.token).to eql("asdf")
50
+ end
51
+ end
52
+
53
+ it "inits the octokit client" do
54
+ with_env "GITHUB_TOKEN", "asdf" do
55
+ expect(@helper.client.class).to eql(Octokit::Client)
56
+ expect(@helper.client.access_token).to eql("asdf")
57
+ end
58
+ end
59
+
60
+ it "grabs the form data from the session" do
61
+ expected = {"title" => "title", "foo" => "bar"}
62
+ @helper.session["form_data"] = expected.to_json
63
+ expect(@helper.form_data).to eql(expected)
64
+ end
65
+
66
+ it "grabs the form data when posted" do
67
+ expected = {"title" => "title", "foo" => "bar"}
68
+ @helper.params = expected
69
+ expect(@helper.form_data).to eql(expected)
70
+ end
71
+
72
+ it "builds the issue body" do
73
+ expected = {"title" => "title", "foo" => "bar"}
74
+ @helper.params = expected
75
+ expect(@helper.issue_body).to eql("* **Foo**: bar")
76
+ end
77
+
78
+ it "submits the issue" do
79
+ expected = {"title" => "title", "foo" => "bar"}
80
+ @helper.params = expected
81
+ with_env "GITHUB_TOKEN", "1234" do
82
+ with_env "GITHUB_REPO", "benbalter/test-repo-ignore-me" do
83
+
84
+ stub = stub_request(:post, "https://api.github.com/repos/benbalter/test-repo-ignore-me/issues").
85
+ with(:body => "{\"labels\":[],\"title\":\"title\",\"body\":\"* **Foo**: bar\"}").
86
+ to_return(:status => 200)
87
+
88
+ @helper.create_issue
89
+ expect(stub).to have_been_requested
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,140 @@
1
+ require "spec_helper"
2
+
3
+ describe "ProblemChild" do
4
+ it "knows the root" do
5
+ expected = File.expand_path "../lib/problem_child", File.dirname(__FILE__)
6
+ expect(ProblemChild.root).to eql(expected)
7
+ end
8
+
9
+ it "knows the views dir" do
10
+ expected = File.expand_path "../lib/problem_child/views", File.dirname(__FILE__)
11
+ expect(ProblemChild.views_dir).to eql(expected)
12
+ end
13
+
14
+ it "allows users to set the views dir" do
15
+ old = ProblemChild.views_dir
16
+ ProblemChild.views_dir = "./foo"
17
+ expect(ProblemChild.views_dir).to eql("./foo")
18
+ ProblemChild.views_dir = old
19
+ end
20
+ end
21
+
22
+ describe "logged in user" do
23
+
24
+ before(:each) do
25
+ @user = make_user('login' => 'benbaltertest')
26
+ login_as @user
27
+
28
+ ENV["GITHUB_TEAM_ID"] = nil
29
+ ENV["GITHUB_ORG_ID"] = nil
30
+ ENV["GITHUB_TOKEN"] = nil
31
+ ENV["GITHUB_REPO"] = nil
32
+ end
33
+
34
+ include Rack::Test::Methods
35
+
36
+ def app
37
+ ProblemChild::App
38
+ end
39
+
40
+ it "shows the securocat when github returns an oauth error" do
41
+ with_env "GITHUB_ORG_ID", "balter-test-org" do
42
+ get "/auth/github/callback?error=redirect_uri_mismatch"
43
+ follow_redirect!
44
+ expect(last_response.body).to match(%r{securocat\.png})
45
+ end
46
+ end
47
+
48
+ it "shows the form when properly org auth'd" do
49
+ with_env "GITHUB_ORG_ID", "balter-test-org" do
50
+ stub_request(:get, "https://api.github.com/orgs/balter-test-org/members/benbaltertest").
51
+ to_return(:status => 204)
52
+
53
+ get "/"
54
+ expect(last_response.status).to eql(200)
55
+ expect(last_response.body).to match(/Submit an issue/)
56
+ end
57
+ end
58
+
59
+ it "shows the form when properly team auth'd" do
60
+ with_env "GITHUB_TEAM_ID", "1234" do
61
+ stub_request(:get, "https://api.github.com/teams/1234/members/benbaltertest").
62
+ to_return(:status => 204)
63
+
64
+ get "/"
65
+ expect(last_response.status).to eql(200)
66
+ expect(last_response.body).to match(/Submit an issue/)
67
+ end
68
+ end
69
+
70
+ it "refuses to show the site with no auth strategy" do
71
+ with_env "GITHUB_TEAM_ID", nil do
72
+ with_env "GITHUB_ORG_ID", nil do
73
+ with_env "GITHUB_TOKEN", nil do
74
+ expect{get "/"}.to raise_error(/Must define GITHUB_TEAM_ID, GITHUB_ORG_ID, OR GITHUB_TOKEN/)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ it "allows the user to create an issue" do
81
+ with_env "GITHUB_ORG_ID", "balter-test-org" do
82
+ with_env "GITHUB_REPO", "benbalter/test-repo-ignore-me" do
83
+
84
+ stub_request(:get, "https://api.github.com/orgs/balter-test-org/members/benbaltertest").
85
+ to_return(:status => 204)
86
+
87
+ stub_request(:post, "https://api.github.com/repos/benbalter/test-repo-ignore-me/issues").
88
+ with(:body => "{\"labels\":[],\"title\":\"title\",\"body\":\"* **Foo**: bar\"}").
89
+ to_return(:status => 200)
90
+
91
+ post "/", :title => "title", :foo => "bar"
92
+ follow_redirect!
93
+
94
+ expect(last_response.status).to eql(200)
95
+ expect(last_response.body).to match(/Your issue was successfully submitted/)
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "logged out user" do
102
+ include Rack::Test::Methods
103
+
104
+ def app
105
+ ProblemChild::App
106
+ end
107
+
108
+ it "asks the user to log in" do
109
+ with_env "GITHUB_ORG_ID", "balter-test-org" do
110
+ get "/"
111
+ expect(last_response.status).to eql(302)
112
+ expect(last_response.headers['Location']).to match(%r{^https://github\.com/login/oauth/authorize})
113
+ end
114
+ end
115
+
116
+ it "allows anonymous users to see the form" do
117
+ with_env "GITHUB_TOKEN", "1234" do
118
+ get "/"
119
+ expect(last_response.status).to eql(200)
120
+ expect(last_response.body).to match(/Submit an issue/)
121
+ end
122
+ end
123
+
124
+ it "allows anonymous submissions" do
125
+ with_env "GITHUB_TOKEN", "1234" do
126
+ with_env "GITHUB_REPO", "benbalter/test-repo-ignore-me" do
127
+
128
+ stub_request(:post, "https://api.github.com/repos/benbalter/test-repo-ignore-me/issues").
129
+ with(:body => "{\"labels\":[],\"title\":\"title\",\"body\":\"* **Foo**: bar\"}").
130
+ to_return(:status => 200)
131
+
132
+ post "/", :title => "title", :foo => "bar"
133
+ follow_redirect!
134
+
135
+ expect(last_response.status).to eql(200)
136
+ expect(last_response.body).to match(/Your issue was successfully submitted/)
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,23 @@
1
+ require "bundler/setup"
2
+
3
+ ENV['RACK_ENV'] = 'test'
4
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
5
+
6
+ require 'rack/test'
7
+ require 'sinatra/auth/github'
8
+ require 'sinatra/auth/github/test/test_helper'
9
+ require 'webmock/rspec'
10
+
11
+ require_relative "../lib/problem_child"
12
+ WebMock.disable_net_connect!
13
+
14
+ RSpec.configure do |config|
15
+ config.include(Sinatra::Auth::Github::Test::Helper)
16
+ end
17
+
18
+ def with_env(key, value)
19
+ old_env = ENV[key]
20
+ ENV[key] = value
21
+ yield
22
+ ENV[key] = old_env
23
+ end
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: 0.0.2
4
+ version: 0.0.3
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-01-09 00:00:00.000000000 Z
11
+ date: 2015-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -108,6 +108,48 @@ dependencies:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
110
  version: 1.5.2
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rack-test
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.6'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.6'
139
+ - !ruby/object:Gem::Dependency
140
+ name: webmock
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.2'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.2'
111
153
  - !ruby/object:Gem::Dependency
112
154
  name: foreman
113
155
  requirement: !ruby/object:Gem::Requirement
@@ -173,6 +215,7 @@ extra_rdoc_files: []
173
215
  files:
174
216
  - ".bowerrc"
175
217
  - ".gitignore"
218
+ - ".travis.yml"
176
219
  - Gemfile
177
220
  - LICENSE.txt
178
221
  - Procfile
@@ -181,6 +224,7 @@ files:
181
224
  - bower.json
182
225
  - config.ru
183
226
  - lib/problem_child.rb
227
+ - lib/problem_child/helpers.rb
184
228
  - lib/problem_child/public/vendor/bootstrap/.bower.json
185
229
  - lib/problem_child/public/vendor/bootstrap/Gruntfile.js
186
230
  - lib/problem_child/public/vendor/bootstrap/LICENSE
@@ -229,9 +273,13 @@ files:
229
273
  - lib/problem_child/views/layout.erb
230
274
  - problem_child.gemspec
231
275
  - script/bootstrap
276
+ - script/cibuild
232
277
  - script/console
233
278
  - script/release
234
279
  - script/server
280
+ - spec/problem_child_helpers_spec.rb
281
+ - spec/problem_child_spec.rb
282
+ - spec/spec_helper.rb
235
283
  homepage: https://github.com/benbalter/problem_child
236
284
  licenses:
237
285
  - MIT
@@ -257,4 +305,7 @@ signing_key:
257
305
  specification_version: 4
258
306
  summary: Allows authenticated or anonymous users to fill out a standard web form to
259
307
  creat GitHub issues.
260
- test_files: []
308
+ test_files:
309
+ - spec/problem_child_helpers_spec.rb
310
+ - spec/problem_child_spec.rb
311
+ - spec/spec_helper.rb