Commit 14a18a0c5a80cb7bedf5f2c13244d28eabc994ef
1 parent
400beb72
Exists in
master
and in
1 other branch
Refactored and wrote specs to cover GitHub integration. Renamed [gG]it[hH]ub => GitHub.
Showing
12 changed files
with
139 additions
and
53 deletions
Show diff stats
README.md
@@ -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 < IssueTracker | @@ -6,7 +6,7 @@ class IssueTrackers::GithubIssuesTracker < 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 < IssueTracker | @@ -15,7 +15,7 @@ class IssueTrackers::GithubIssuesTracker < 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 < IssueTracker | @@ -25,7 +25,7 @@ class IssueTrackers::GithubIssuesTracker < 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 'capybara/rspec' | @@ -3,16 +3,17 @@ require 'capybara/rspec' | ||
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 |
@@ -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
spec/views/users/show.html.haml_spec.rb
@@ -5,11 +5,12 @@ describe 'users/show.html.haml' do | @@ -5,11 +5,12 @@ describe 'users/show.html.haml' 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 'users/show.html.haml' do | @@ -25,4 +26,35 @@ describe 'users/show.html.haml' 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 |