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.

README.md
... ... @@ -258,10 +258,10 @@ Issue Trackers
258 258 * Project id is the identifier of your project, i.e. **awesomeapp** for project at https://mingle.example.com/projects/awesomeapp
259 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 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 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 271 Errbit will log it's own errors to an internal app named **Self.Errbit**.
272 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 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 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 282 3. Fill in the **Account/Repository** field with **errbit/errbit**.
283 283  
284 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 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 293 TODO
... ...
app/controllers/users/omniauth_callbacks_controller.rb
1 1 class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
2 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 5 github_user = User.where(:github_login => github_login).first
6 6  
7 7 # If user is already signed in, link github details to their account
8 8 if current_user
9 9 # ... unless a user is already registered with same github login
10 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 12 else
14 13 # Add github details to current user
15 14 current_user.update_attributes(
16 15 :github_login => github_login,
17 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 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 22 elsif github_user
24 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 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 30 redirect_to new_user_session_path
31 31 end
32 32 end
... ...
app/models/issue_trackers/github_issues_tracker.rb
... ... @@ -6,7 +6,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker
6 6 :placeholder => "errbit/errbit from https://github.com/errbit/errbit"
7 7 }],
8 8 [:username, {
9   - :placeholder => "Your username on Github"
  9 + :placeholder => "Your username on GitHub"
10 10 }],
11 11 [:password, {
12 12 :placeholder => "Password for your account"
... ... @@ -15,7 +15,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker
15 15  
16 16 def check_params
17 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 19 end
20 20 end
21 21  
... ... @@ -25,7 +25,7 @@ class IssueTrackers::GithubIssuesTracker &lt; IssueTracker
25 25 issue = client.create_issue(project_id, issue_title(problem), body_template.result(binding).unpack('C*').pack('U*'), options = {})
26 26 problem.update_attribute :issue_link, issue.html_url
27 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 29 end
30 30 end
31 31  
... ...
app/views/users/show.html.haml
... ... @@ -6,7 +6,6 @@
6 6 = link_to 'destroy', user_path(@user), :method => :delete, :confirm => 'Seriously?', :class => 'button'
7 7  
8 8  
9   -
10 9 %table.single_user
11 10 %tr
12 11 %th Email
... ...
config/config.example.yml
... ... @@ -49,8 +49,8 @@ deployment:
49 49 user: deploy
50 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 54 # your app at: https://github.com/settings/applications
55 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 3  
4 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 19 end
... ...
spec/acceptance/login_spec.rb
... ... @@ -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 @@
  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 @@
  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 1 require 'spec_helper'
2 2  
3 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 5 notice = Fabricate :notice
6 6 tracker = Fabricate :github_issues_tracker, :app => notice.app
7 7 problem = notice.problem
... ...
spec/spec_helper.rb
... ... @@ -27,3 +27,5 @@ RSpec.configure do |config|
27 27 end
28 28 config.include WebMock::API
29 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 5 user = stub_model(User, :created_at => Time.now)
6 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 14 it 'shows github login' do
14 15 user.github_login = 'test_user'
15 16 assign :user, user
... ... @@ -25,4 +26,35 @@ describe &#39;users/show.html.haml&#39; do
25 26 rendered.should_not match(/GitHub/)
26 27 end
27 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 60 end
... ...