Commit 14a18a0c5a80cb7bedf5f2c13244d28eabc994ef

Authored by Nathan Broadbent
1 parent 400beb72
Exists in master and in 1 other branch production

Refactored and wrote specs to cover GitHub integration. Renamed [gG]it[hH]ub => GitHub.

@@ -258,10 +258,10 @@ Issue Trackers @@ -258,10 +258,10 @@ Issue Trackers
258 * Project id is the identifier of your project, i.e. **awesomeapp** for project at https://mingle.example.com/projects/awesomeapp 258 * Project id is the identifier of your project, i.e. **awesomeapp** for project at https://mingle.example.com/projects/awesomeapp
259 * Card properties are comma separated key value pairs. You must specify a 'card_type', but anything else is optional. i.e. card_type = Defect, status = Open, priority = Essential 259 * Card properties are comma separated key value pairs. You must specify a 'card_type', but anything else is optional. i.e. card_type = Defect, status = Open, priority = Essential
260 260
261 -**Github Issues Integration** 261 +**GitHub Issues Integration**
262 262
263 * For 'Account/Repository', the account will either be a username or organization. i.e. **errbit/errbit** 263 * For 'Account/Repository', the account will either be a username or organization. i.e. **errbit/errbit**
264 -* You will also need to provide your username and password for your Github account. 264 +* You will also need to provide your username and password for your GitHub account.
265 * (We'd really appreciate it if you wanted to help us implement OAuth instead!) 265 * (We'd really appreciate it if you wanted to help us implement OAuth instead!)
266 266
267 267
@@ -271,23 +271,23 @@ What if Errbit has an error? @@ -271,23 +271,23 @@ What if Errbit has an error?
271 Errbit will log it's own errors to an internal app named **Self.Errbit**. 271 Errbit will log it's own errors to an internal app named **Self.Errbit**.
272 The **Self.Errbit** app will be automatically created whenever the first error happens. 272 The **Self.Errbit** app will be automatically created whenever the first error happens.
273 273
274 -If your Errbit instance has logged an error, we would appreciate a bug report on Github Issues. 274 +If your Errbit instance has logged an error, we would appreciate a bug report on GitHub Issues.
275 You can post this manually at [https://github.com/errbit/errbit/issues](https://github.com/errbit/errbit/issues), 275 You can post this manually at [https://github.com/errbit/errbit/issues](https://github.com/errbit/errbit/issues),
276 -or you can set up the Github Issues tracker for your **Self.Errbit** app: 276 +or you can set up the GitHub Issues tracker for your **Self.Errbit** app:
277 277
278 1. Go to the **Self.Errbit** app's edit page. If that app does not exist yet, go to the apps page and click **Add a new App** to create it. (You can also create it by running `rake airbrake:test`.) 278 1. Go to the **Self.Errbit** app's edit page. If that app does not exist yet, go to the apps page and click **Add a new App** to create it. (You can also create it by running `rake airbrake:test`.)
279 279
280 - 2. In the **Issue Tracker** section, click **Github Issues**. 280 + 2. In the **Issue Tracker** section, click **GitHub Issues**.
281 281
282 3. Fill in the **Account/Repository** field with **errbit/errbit**. 282 3. Fill in the **Account/Repository** field with **errbit/errbit**.
283 283
284 4. Fill in the **Username** field with your github username. 284 4. Fill in the **Username** field with your github username.
285 285
286 - 5. If you are logged in on [Github](https://github.com), you can find your **API Token** on this page: [https://github.com/account/admin](https://github.com/account/admin). 286 + 5. If you are logged in on [GitHub](https://github.com), you can find your **API Token** on this page: [https://github.com/account/admin](https://github.com/account/admin).
287 287
288 6. Save the settings by clicking **Update App** (or **Add App**) 288 6. Save the settings by clicking **Update App** (or **Add App**)
289 289
290 - 7. You can now easily post bug reports to Github Issues by clicking the **Create Issue** button on a **Self.Errbit** error. 290 + 7. You can now easily post bug reports to GitHub Issues by clicking the **Create Issue** button on a **Self.Errbit** error.
291 291
292 292
293 TODO 293 TODO
app/controllers/users/omniauth_callbacks_controller.rb
1 class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 1 class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
2 def github 2 def github
3 - github_login = request.env["omniauth.auth"].extra.raw_info.login  
4 - github_token = request.env["omniauth.auth"].credentials.token 3 + github_login = env["omniauth.auth"].extra.raw_info.login
  4 + github_token = env["omniauth.auth"].credentials.token
5 github_user = User.where(:github_login => github_login).first 5 github_user = User.where(:github_login => github_login).first
6 6
7 # If user is already signed in, link github details to their account 7 # If user is already signed in, link github details to their account
8 if current_user 8 if current_user
9 # ... unless a user is already registered with same github login 9 # ... unless a user is already registered with same github login
10 if github_user && github_user != current_user 10 if github_user && github_user != current_user
11 - flash[:error] = "User already registered with Github login '#{github_login}'"  
12 - redirect_to user_path(current_user) 11 + flash[:error] = "User already registered with GitHub login '#{github_login}'"
13 else 12 else
14 # Add github details to current user 13 # Add github details to current user
15 current_user.update_attributes( 14 current_user.update_attributes(
16 :github_login => github_login, 15 :github_login => github_login,
17 :github_oauth_token => github_token 16 :github_oauth_token => github_token
18 ) 17 )
19 - flash[:success] = "Successfully linked Github account!"  
20 - redirect_to user_path(current_user) 18 + flash[:success] = "Successfully linked GitHub account!"
21 end 19 end
22 - 20 + # User must have clicked 'link account' from their user page, so redirect there.
  21 + redirect_to user_path(current_user)
23 elsif github_user 22 elsif github_user
24 # Store OAuth token 23 # Store OAuth token
25 - @user.update_attribute :github_oauth_token, request.env["omniauth.auth"].credentials.token 24 + github_user.update_attribute :github_oauth_token, github_token
26 25
27 - flash[:success] = I18n.t "devise.omniauth_callbacks.success", :kind => "Github"  
28 - sign_in_and_redirect @user, :event => :authentication 26 + flash[:success] = I18n.t "devise.omniauth_callbacks.success", :kind => "GitHub"
  27 + sign_in_and_redirect github_user, :event => :authentication
29 else 28 else
  29 + flash[:error] = "There are no authorized users with GitHub login '#{github_login}'. Please ask an administrator to register your user account."
30 redirect_to new_user_session_path 30 redirect_to new_user_session_path
31 end 31 end
32 end 32 end
app/models/issue_trackers/github_issues_tracker.rb
@@ -6,7 +6,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker @@ -6,7 +6,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker
6 :placeholder => "errbit/errbit from https://github.com/errbit/errbit" 6 :placeholder => "errbit/errbit from https://github.com/errbit/errbit"
7 }], 7 }],
8 [:username, { 8 [:username, {
9 - :placeholder => "Your username on Github" 9 + :placeholder => "Your username on GitHub"
10 }], 10 }],
11 [:password, { 11 [:password, {
12 :placeholder => "Password for your account" 12 :placeholder => "Password for your account"
@@ -15,7 +15,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker @@ -15,7 +15,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker
15 15
16 def check_params 16 def check_params
17 if Fields.detect {|f| self[f[0]].blank? } 17 if Fields.detect {|f| self[f[0]].blank? }
18 - errors.add :base, 'You must specify your Github repository, username and password' 18 + errors.add :base, 'You must specify your GitHub repository, username and password'
19 end 19 end
20 end 20 end
21 21
@@ -25,7 +25,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker @@ -25,7 +25,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker
25 issue = client.create_issue(project_id, issue_title(problem), body_template.result(binding).unpack('C*').pack('U*'), options = {}) 25 issue = client.create_issue(project_id, issue_title(problem), body_template.result(binding).unpack('C*').pack('U*'), options = {})
26 problem.update_attribute :issue_link, issue.html_url 26 problem.update_attribute :issue_link, issue.html_url
27 rescue Octokit::Unauthorized 27 rescue Octokit::Unauthorized
28 - raise IssueTrackers::AuthenticationError, "Could not authenticate with Github. Please check your username and password." 28 + raise IssueTrackers::AuthenticationError, "Could not authenticate with GitHub. Please check your username and password."
29 end 29 end
30 end 30 end
31 31
app/views/users/show.html.haml
@@ -6,7 +6,6 @@ @@ -6,7 +6,6 @@
6 = link_to 'destroy', user_path(@user), :method => :delete, :confirm => 'Seriously?', :class => 'button' 6 = link_to 'destroy', user_path(@user), :method => :delete, :confirm => 'Seriously?', :class => 'button'
7 7
8 8
9 -  
10 %table.single_user 9 %table.single_user
11 %tr 10 %tr
12 %th Email 11 %th Email
config/config.example.yml
@@ -49,8 +49,8 @@ deployment: @@ -49,8 +49,8 @@ deployment:
49 user: deploy 49 user: deploy
50 deploy_to: /var/www/apps/errbit 50 deploy_to: /var/www/apps/errbit
51 51
52 -# Github OAuth configuration  
53 -# If you want to allow authentication via Github, you will need to register 52 +# GitHub OAuth configuration
  53 +# If you want to allow authentication via GitHub, you will need to register
54 # your app at: https://github.com/settings/applications 54 # your app at: https://github.com/settings/applications
55 # If you hosted Errbit at errbit.example.com, you would fill in: 55 # If you hosted Errbit at errbit.example.com, you would fill in:
56 # 56 #
spec/acceptance/acceptance_helper.rb
@@ -3,16 +3,17 @@ require &#39;capybara/rspec&#39; @@ -3,16 +3,17 @@ require &#39;capybara/rspec&#39;
3 3
4 OmniAuth.config.test_mode = true 4 OmniAuth.config.test_mode = true
5 5
6 -RSpec.configure do |config|  
7 - config.before(:each) do  
8 - OmniAuth.config.mock_auth[:github] = Hashie::Mash.new(  
9 - 'provider' => 'github',  
10 - 'uid' => '1763',  
11 - 'extra' => {  
12 - 'raw_info' => {  
13 - 'login' => 'nashby'  
14 - } 6 +def mock_auth(user = "test_user", token = "abcdef")
  7 + OmniAuth.config.mock_auth[:github] = Hashie::Mash.new(
  8 + 'provider' => 'github',
  9 + 'uid' => '1763',
  10 + 'extra' => {
  11 + 'raw_info' => {
  12 + 'login' => user
15 } 13 }
16 - )  
17 - end 14 + },
  15 + 'credentials' => {
  16 + 'token' => token
  17 + }
  18 + )
18 end 19 end
spec/acceptance/login_spec.rb
@@ -1,14 +0,0 @@ @@ -1,14 +0,0 @@
1 -require 'acceptance/acceptance_helper'  
2 -  
3 -feature 'Log in' do  
4 - background do  
5 - Errbit::Config.stub(:github_authentication) { true }  
6 - Fabricate(:user, :github_login => 'nashby')  
7 - end  
8 -  
9 - scenario 'log in via GitHub' do  
10 - visit '/'  
11 - click_link 'Sign in with GitHub'  
12 - page.should have_content 'Successfully authorized from Github account'  
13 - end  
14 -end  
spec/acceptance/sign_in_with_github_spec.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +require 'acceptance/acceptance_helper'
  2 +
  3 +feature 'Sign in with GitHub' do
  4 + background do
  5 + Errbit::Config.stub(:github_authentication) { true }
  6 + Fabricate(:user, :github_login => 'nashby')
  7 + end
  8 +
  9 + scenario 'log in via GitHub with recognized user' do
  10 + mock_auth('nashby')
  11 +
  12 + visit '/'
  13 + click_link 'Sign in with GitHub'
  14 + page.should have_content 'Successfully authorized from GitHub account'
  15 + end
  16 +
  17 + scenario 'reject unrecognized user if authenticating via GitHub' do
  18 + mock_auth('unknown_user')
  19 +
  20 + visit '/'
  21 + click_link 'Sign in with GitHub'
  22 + page.should have_content 'There are no authorized users with GitHub login'
  23 + end
  24 +end
spec/controllers/users/omniauth_callbacks_controller_spec.rb 0 → 100644
@@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Users::OmniauthCallbacksController do
  4 +
  5 + def stub_env_for_github_omniauth(login, token = nil)
  6 + # This a Devise specific thing for functional tests. See https://github.com/plataformatec/devise/issues/closed#issue/608
  7 + request.env["devise.mapping"] = Devise.mappings[:user]
  8 + env = {
  9 + "omniauth.auth" => Hashie::Mash.new(
  10 + :provider => 'github',
  11 + :extra => { :raw_info => { :login => login }},
  12 + :credentials => { :token => token }
  13 + )
  14 + }
  15 + @controller.stub!(:env).and_return(env)
  16 + end
  17 +
  18 + context 'Linking a GitHub account to a signed in user' do
  19 + before do
  20 + sign_in @user = Fabricate(:user)
  21 + end
  22 +
  23 + it "should show an error if another user already has that github login" do
  24 + Fabricate(:user, :github_login => "existing_user")
  25 + stub_env_for_github_omniauth("existing_user")
  26 + get :github
  27 +
  28 + request.flash[:error].should include('already registered')
  29 + response.should redirect_to(user_path(@user))
  30 + end
  31 +
  32 + it "should link an authorized GitHub account" do
  33 + stub_env_for_github_omniauth("new_user")
  34 + get :github
  35 +
  36 + request.flash[:success].should include('Successfully linked')
  37 + response.should redirect_to(user_path(@user))
  38 + end
  39 + end
  40 +
  41 + # See spec/acceptance/sign_in_with_github_spec.rb for 'Signing in with github' integration tests.
  42 +end
spec/models/issue_trackers/github_issues_tracker_spec.rb
1 require 'spec_helper' 1 require 'spec_helper'
2 2
3 describe IssueTrackers::GithubIssuesTracker do 3 describe IssueTrackers::GithubIssuesTracker do
4 - it "should create an issue on Github Issues with problem params, and set issue link for problem" do 4 + it "should create an issue on GitHub Issues with problem params, and set issue link for problem" do
5 notice = Fabricate :notice 5 notice = Fabricate :notice
6 tracker = Fabricate :github_issues_tracker, :app => notice.app 6 tracker = Fabricate :github_issues_tracker, :app => notice.app
7 problem = notice.problem 7 problem = notice.problem
spec/spec_helper.rb
@@ -27,3 +27,5 @@ RSpec.configure do |config| @@ -27,3 +27,5 @@ RSpec.configure do |config|
27 end 27 end
28 config.include WebMock::API 28 config.include WebMock::API
29 end 29 end
  30 +
  31 +OmniAuth.config.test_mode = true
spec/views/users/show.html.haml_spec.rb
@@ -5,11 +5,12 @@ describe &#39;users/show.html.haml&#39; do @@ -5,11 +5,12 @@ describe &#39;users/show.html.haml&#39; do
5 user = stub_model(User, :created_at => Time.now) 5 user = stub_model(User, :created_at => Time.now)
6 end 6 end
7 7
8 - context 'with github auth' do  
9 - before do  
10 - Errbit::Config.stub(:github_authentication) { true }  
11 - end 8 + before do
  9 + Errbit::Config.stub(:github_authentication) { true }
  10 + controller.stub(:current_user) { Fabricate(:user) }
  11 + end
12 12
  13 + context 'with GitHub authentication' do
13 it 'shows github login' do 14 it 'shows github login' do
14 user.github_login = 'test_user' 15 user.github_login = 'test_user'
15 assign :user, user 16 assign :user, user
@@ -25,4 +26,35 @@ describe &#39;users/show.html.haml&#39; do @@ -25,4 +26,35 @@ describe &#39;users/show.html.haml&#39; do
25 rendered.should_not match(/GitHub/) 26 rendered.should_not match(/GitHub/)
26 end 27 end
27 end 28 end
  29 +
  30 + context "Linking GitHub account" do
  31 + context 'viewing another user page' do
  32 + it "doesn't show and github linking buttons if user is not current user" do
  33 + assign :user, user
  34 + render
  35 + view.content_for(:action_bar).should_not include('Link GitHub account')
  36 + view.content_for(:action_bar).should_not include('Unlink GitHub account')
  37 + end
  38 + end
  39 +
  40 + context 'viewing own user page' do
  41 + before do
  42 + @user = Fabricate(:user)
  43 + controller.stub!(:current_user).and_return(@user)
  44 + assign :user, @user
  45 + end
  46 +
  47 + it 'shows link github button when no login or token' do
  48 + render
  49 + view.content_for(:action_bar).should include('Link GitHub account')
  50 + end
  51 +
  52 + it 'shows unlink github button when login and token' do
  53 + @user.github_login = 'test_user'
  54 + @user.github_oauth_token = 'abcdef'
  55 + render
  56 + view.content_for(:action_bar).should include('Unlink GitHub account')
  57 + end
  58 + end
  59 + end
28 end 60 end