Commit 8f13caf0bffe3dfd579dc52b76f54fe84c943154
1 parent
b4fc56cc
Exists in
master
and in
1 other branch
Add capabilities to addmin to regenerate the API key of his app
Now the api_key of app can be regenerate. In previous this api-key can't be regenerate by the web front. To regenerate this api_key you need go to the edit app page. See #547
Showing
12 changed files
with
164 additions
and
63 deletions
Show diff stats
app/controllers/apps_controller.rb
@@ -80,6 +80,11 @@ class AppsController < ApplicationController | @@ -80,6 +80,11 @@ class AppsController < ApplicationController | ||
80 | end | 80 | end |
81 | end | 81 | end |
82 | 82 | ||
83 | + def regenerate_api_key | ||
84 | + app.regenerate_api_key! | ||
85 | + redirect_to edit_app_path(app) | ||
86 | + end | ||
87 | + | ||
83 | protected | 88 | protected |
84 | 89 | ||
85 | def initialize_subclassed_issue_tracker | 90 | def initialize_subclassed_issue_tracker |
app/models/app.rb
@@ -170,6 +170,10 @@ class App | @@ -170,6 +170,10 @@ class App | ||
170 | Errbit::Config.per_app_email_at_notices ? super : Errbit::Config.email_at_notices | 170 | Errbit::Config.per_app_email_at_notices ? super : Errbit::Config.email_at_notices |
171 | end | 171 | end |
172 | 172 | ||
173 | + def regenerate_api_key! | ||
174 | + set(:api_key, SecureRandom.hex) | ||
175 | + end | ||
176 | + | ||
173 | protected | 177 | protected |
174 | 178 | ||
175 | def store_cached_attributes_on_problems | 179 | def store_cached_attributes_on_problems |
app/views/apps/_fields.html.haml
@@ -5,6 +5,10 @@ | @@ -5,6 +5,10 @@ | ||
5 | = f.text_field :name | 5 | = f.text_field :name |
6 | 6 | ||
7 | %div | 7 | %div |
8 | + %label Api Key | ||
9 | + %span= app.api_key | ||
10 | + = link_to t('.regenerate_api_key'), regenerate_api_key_app_path(app), :class => 'button', :method => 'post' | ||
11 | +%div | ||
8 | = f.label :repository_branch | 12 | = f.label :repository_branch |
9 | = f.text_field :repository_branch, :placeholder => "master" | 13 | = f.text_field :repository_branch, :placeholder => "master" |
10 | %div | 14 | %div |
config/locales/en.yml
@@ -81,6 +81,8 @@ en: | @@ -81,6 +81,8 @@ en: | ||
81 | new_app: Add a New App | 81 | new_app: Add a New App |
82 | no_apps: 'No apps here.' | 82 | no_apps: 'No apps here.' |
83 | click_to_create: 'Click here to create your first one' | 83 | click_to_create: 'Click here to create your first one' |
84 | + fields: | ||
85 | + regenerate_api_key: "Regenerate API key" | ||
84 | show: | 86 | show: |
85 | all_deploys: "All Deploys (%{count})" | 87 | all_deploys: "All Deploys (%{count})" |
86 | all_errs: all errs | 88 | all_errs: all errs |
@@ -100,7 +102,6 @@ en: | @@ -100,7 +102,6 @@ en: | ||
100 | no_error_yet: "No errs have been caught yet, make sure you setup your app" | 102 | no_error_yet: "No errs have been caught yet, make sure you setup your app" |
101 | no_watcher: "Sadly, no one is watching this app" | 103 | no_watcher: "Sadly, no one is watching this app" |
102 | repository: Repository | 104 | repository: Repository |
103 | - repository: Repository | ||
104 | revision: Revision | 105 | revision: Revision |
105 | search_placeholder: 'Search for issues' | 106 | search_placeholder: 'Search for issues' |
106 | show_hide: "(show/hide)" | 107 | show_hide: "(show/hide)" |
@@ -110,3 +111,4 @@ en: | @@ -110,3 +111,4 @@ en: | ||
110 | watchers: Watchers | 111 | watchers: Watchers |
111 | when: When | 112 | when: When |
112 | who: Who | 113 | who: Who |
114 | + |
config/routes.rb
@@ -39,6 +39,9 @@ Errbit::Application.routes.draw do | @@ -39,6 +39,9 @@ Errbit::Application.routes.draw do | ||
39 | end | 39 | end |
40 | resources :deploys, :only => [:index] | 40 | resources :deploys, :only => [:index] |
41 | resources :watchers, :only => [:destroy] | 41 | resources :watchers, :only => [:destroy] |
42 | + member do | ||
43 | + post :regenerate_api_key | ||
44 | + end | ||
42 | end | 45 | end |
43 | 46 | ||
44 | namespace :api do | 47 | namespace :api do |
spec/acceptance/acceptance_helper.rb
@@ -17,3 +17,10 @@ def mock_auth(user = "test_user", token = "abcdef") | @@ -17,3 +17,10 @@ def mock_auth(user = "test_user", token = "abcdef") | ||
17 | } | 17 | } |
18 | ) | 18 | ) |
19 | end | 19 | end |
20 | + | ||
21 | +def log_in(user) | ||
22 | + visit '/' | ||
23 | + fill_in :user_email, :with => user.email | ||
24 | + fill_in :user_password, :with => 'password' | ||
25 | + click_on I18n.t('devise.sessions.new.sign_in') | ||
26 | +end |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +require 'acceptance/acceptance_helper' | ||
2 | + | ||
3 | +feature "Regeneration api_Key" do | ||
4 | + let!(:app) { Fabricate(:app) } | ||
5 | + let!(:admin) { Fabricate(:admin) } | ||
6 | + let(:user) { | ||
7 | + Fabricate(:user_watcher, :app => app).user | ||
8 | + } | ||
9 | + | ||
10 | + scenario "an admin change api_key" do | ||
11 | + visit '/' | ||
12 | + log_in admin | ||
13 | + click_link app.name | ||
14 | + click_link I18n.t('apps.show.edit') | ||
15 | + expect { | ||
16 | + click_link I18n.t('apps.fields.regenerate_api_key') | ||
17 | + }.to change { | ||
18 | + app.reload.api_key | ||
19 | + } | ||
20 | + end | ||
21 | + | ||
22 | + scenario "a user cannot access to edit page" do | ||
23 | + visit '/' | ||
24 | + log_in user | ||
25 | + click_link app.name if page.current_url != app_url(app) | ||
26 | + expect(page).to_not have_button I18n.t('apps.show.edit') | ||
27 | + end | ||
28 | + | ||
29 | +end |
spec/acceptance/watch_unwatch_app.rb
@@ -1,23 +0,0 @@ | @@ -1,23 +0,0 @@ | ||
1 | -require 'acceptance/acceptance_helper' | ||
2 | - | ||
3 | -feature 'A user can watch and unwatch an application' do | ||
4 | - | ||
5 | - let!(:app) { Fabricate(:app) } | ||
6 | - let!(:user) do | ||
7 | - user = Fabricate(:user) | ||
8 | - app.watchers.create!( | ||
9 | - :user_id => user.id | ||
10 | - ) | ||
11 | - user.reload | ||
12 | - end | ||
13 | - | ||
14 | - scenario 'log in watch a project and unwatch it' do | ||
15 | - visit '/' | ||
16 | - fill_in :user_email, :with => user.email | ||
17 | - fill_in :user_password, :with => 'password' | ||
18 | - click_on I18n.t('devise.sessions.new.sign_in') | ||
19 | - click_on I18n.t('apps.show.unwatch') | ||
20 | - expect(page).to have_content(I18n.t('apps.index.no_apps') | ||
21 | - end | ||
22 | - | ||
23 | -end |
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +require 'acceptance/acceptance_helper' | ||
2 | + | ||
3 | +feature 'A user can watch and unwatch an application' do | ||
4 | + | ||
5 | + let!(:app) { Fabricate(:app) } | ||
6 | + let!(:user) do | ||
7 | + user = Fabricate(:user) | ||
8 | + app.watchers.create!( | ||
9 | + :user_id => user.id | ||
10 | + ) | ||
11 | + user.reload | ||
12 | + end | ||
13 | + | ||
14 | + scenario 'log in watch a project and unwatch it' do | ||
15 | + log_in user | ||
16 | + click_on I18n.t('apps.show.unwatch') | ||
17 | + expect(page).to have_content(I18n.t('apps.index.no_apps')) | ||
18 | + end | ||
19 | + | ||
20 | +end |
spec/controllers/apps_controller_spec.rb
@@ -5,11 +5,37 @@ describe AppsController do | @@ -5,11 +5,37 @@ describe AppsController do | ||
5 | it_requires_authentication | 5 | it_requires_authentication |
6 | it_requires_admin_privileges :for => {:new => :get, :edit => :get, :create => :post, :update => :put, :destroy => :delete} | 6 | it_requires_admin_privileges :for => {:new => :get, :edit => :get, :create => :post, :update => :put, :destroy => :delete} |
7 | 7 | ||
8 | + let(:admin) { Fabricate(:admin) } | ||
9 | + let(:user) { Fabricate(:user) } | ||
10 | + let(:watcher) { Fabricate(:user_watcher, :app => app, :user => user) } | ||
11 | + let(:unwatched_app) { Fabricate(:app) } | ||
12 | + let(:app) { unwatched_app } | ||
13 | + let(:watched_app1) do | ||
14 | + a = Fabricate(:app) | ||
15 | + Fabricate(:user_watcher, :user => user, :app => a) | ||
16 | + a | ||
17 | + end | ||
18 | + let(:watched_app2) do | ||
19 | + a = Fabricate(:app) | ||
20 | + Fabricate(:user_watcher, :user => user, :app => a) | ||
21 | + a | ||
22 | + end | ||
23 | + let(:err) do | ||
24 | + Fabricate(:err, :problem => problem) | ||
25 | + end | ||
26 | + let(:notice) do | ||
27 | + Fabricate(:notice, :err => err) | ||
28 | + end | ||
29 | + let(:problem) do | ||
30 | + Fabricate(:problem, :app => app) | ||
31 | + end | ||
32 | + let(:problem_resolved) { Fabricate(:problem_resolved, :app => app) } | ||
33 | + | ||
8 | describe "GET /apps" do | 34 | describe "GET /apps" do |
9 | context 'when logged in as an admin' do | 35 | context 'when logged in as an admin' do |
10 | it 'finds all apps' do | 36 | it 'finds all apps' do |
11 | - sign_in Fabricate(:admin) | ||
12 | - 3.times { Fabricate(:app) } | 37 | + sign_in admin |
38 | + unwatched_app && watched_app1 && watched_app2 | ||
13 | get :index | 39 | get :index |
14 | controller.apps.entries.should == App.all.sort.entries | 40 | controller.apps.entries.should == App.all.sort.entries |
15 | end | 41 | end |
@@ -17,12 +43,8 @@ describe AppsController do | @@ -17,12 +43,8 @@ describe AppsController do | ||
17 | 43 | ||
18 | context 'when logged in as a regular user' do | 44 | context 'when logged in as a regular user' do |
19 | it 'finds apps the user is watching' do | 45 | it 'finds apps the user is watching' do |
20 | - sign_in(user = Fabricate(:user)) | ||
21 | - unwatched_app = Fabricate(:app) | ||
22 | - watched_app1 = Fabricate(:app) | ||
23 | - watched_app2 = Fabricate(:app) | ||
24 | - Fabricate(:user_watcher, :user => user, :app => watched_app1) | ||
25 | - Fabricate(:user_watcher, :user => user, :app => watched_app2) | 46 | + sign_in(user) |
47 | + watched_app1 && watched_app2 && unwatched_app | ||
26 | get :index | 48 | get :index |
27 | controller.apps.should include(watched_app1, watched_app2) | 49 | controller.apps.should include(watched_app1, watched_app2) |
28 | controller.apps.should_not include(unwatched_app) | 50 | controller.apps.should_not include(unwatched_app) |
@@ -33,61 +55,56 @@ describe AppsController do | @@ -33,61 +55,56 @@ describe AppsController do | ||
33 | describe "GET /apps/:id" do | 55 | describe "GET /apps/:id" do |
34 | context 'logged in as an admin' do | 56 | context 'logged in as an admin' do |
35 | before(:each) do | 57 | before(:each) do |
36 | - @user = Fabricate(:admin) | ||
37 | - sign_in @user | ||
38 | - @app = Fabricate(:app) | ||
39 | - @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => @app))).problem | 58 | + sign_in admin |
40 | end | 59 | end |
41 | 60 | ||
42 | it 'finds the app' do | 61 | it 'finds the app' do |
43 | - get :show, :id => @app.id | ||
44 | - controller.app.should == @app | 62 | + get :show, :id => app.id |
63 | + controller.app.should == app | ||
45 | end | 64 | end |
46 | 65 | ||
47 | it "should not raise errors for app with err without notices" do | 66 | it "should not raise errors for app with err without notices" do |
48 | - Fabricate(:err, :problem => Fabricate(:problem, :app => @app)) | ||
49 | - lambda { get :show, :id => @app.id }.should_not raise_error | 67 | + err |
68 | + lambda { get :show, :id => app.id }.should_not raise_error | ||
50 | end | 69 | end |
51 | 70 | ||
52 | it "should list atom feed successfully" do | 71 | it "should list atom feed successfully" do |
53 | - get :show, :id => @app.id, :format => "atom" | 72 | + get :show, :id => app.id, :format => "atom" |
54 | response.should be_success | 73 | response.should be_success |
55 | end | 74 | end |
56 | 75 | ||
57 | context "pagination" do | 76 | context "pagination" do |
58 | before(:each) do | 77 | before(:each) do |
59 | - 35.times { Fabricate(:err, :problem => Fabricate(:problem, :app => @app)) } | 78 | + 35.times { Fabricate(:err, :problem => Fabricate(:problem, :app => app)) } |
60 | end | 79 | end |
61 | 80 | ||
62 | it "should have default per_page value for user" do | 81 | it "should have default per_page value for user" do |
63 | - get :show, :id => @app.id | 82 | + get :show, :id => app.id |
64 | controller.problems.to_a.size.should == User::PER_PAGE | 83 | controller.problems.to_a.size.should == User::PER_PAGE |
65 | end | 84 | end |
66 | 85 | ||
67 | it "should be able to override default per_page value" do | 86 | it "should be able to override default per_page value" do |
68 | - @user.update_attribute :per_page, 10 | ||
69 | - get :show, :id => @app.id | 87 | + admin.update_attribute :per_page, 10 |
88 | + get :show, :id => app.id | ||
70 | controller.problems.to_a.size.should == 10 | 89 | controller.problems.to_a.size.should == 10 |
71 | end | 90 | end |
72 | end | 91 | end |
73 | 92 | ||
74 | context 'with resolved errors' do | 93 | context 'with resolved errors' do |
75 | before(:each) do | 94 | before(:each) do |
76 | - resolved_problem = Fabricate(:problem, :app => @app) | ||
77 | - Fabricate(:notice, :err => Fabricate(:err, :problem => resolved_problem)) | ||
78 | - resolved_problem.resolve! | 95 | + problem_resolved && problem |
79 | end | 96 | end |
80 | 97 | ||
81 | context 'and no params' do | 98 | context 'and no params' do |
82 | it 'shows only unresolved problems' do | 99 | it 'shows only unresolved problems' do |
83 | - get :show, :id => @app.id | 100 | + get :show, :id => app.id |
84 | controller.problems.size.should == 1 | 101 | controller.problems.size.should == 1 |
85 | end | 102 | end |
86 | end | 103 | end |
87 | 104 | ||
88 | context 'and all_problems=true params' do | 105 | context 'and all_problems=true params' do |
89 | it 'shows all errors' do | 106 | it 'shows all errors' do |
90 | - get :show, :id => @app.id, :all_errs => true | 107 | + get :show, :id => app.id, :all_errs => true |
91 | controller.problems.size.should == 2 | 108 | controller.problems.size.should == 2 |
92 | end | 109 | end |
93 | end | 110 | end |
@@ -97,41 +114,41 @@ describe AppsController do | @@ -97,41 +114,41 @@ describe AppsController do | ||
97 | before(:each) do | 114 | before(:each) do |
98 | environments = ['production', 'test', 'development', 'staging'] | 115 | environments = ['production', 'test', 'development', 'staging'] |
99 | 20.times do |i| | 116 | 20.times do |i| |
100 | - Fabricate(:problem, :app => @app, :environment => environments[i % environments.length]) | 117 | + Fabricate(:problem, :app => app, :environment => environments[i % environments.length]) |
101 | end | 118 | end |
102 | end | 119 | end |
103 | 120 | ||
104 | context 'no params' do | 121 | context 'no params' do |
105 | it 'shows errs for all environments' do | 122 | it 'shows errs for all environments' do |
106 | - get :show, :id => @app.id | ||
107 | - controller.problems.size.should == 21 | 123 | + get :show, :id => app.id |
124 | + controller.problems.size.should == 20 | ||
108 | end | 125 | end |
109 | end | 126 | end |
110 | 127 | ||
111 | context 'environment production' do | 128 | context 'environment production' do |
112 | it 'shows errs for just production' do | 129 | it 'shows errs for just production' do |
113 | - get :show, :id => @app.id, :environment => 'production' | ||
114 | - controller.problems.size.should == 6 | 130 | + get :show, :id => app.id, :environment => 'production' |
131 | + controller.problems.size.should == 5 | ||
115 | end | 132 | end |
116 | end | 133 | end |
117 | 134 | ||
118 | context 'environment staging' do | 135 | context 'environment staging' do |
119 | it 'shows errs for just staging' do | 136 | it 'shows errs for just staging' do |
120 | - get :show, :id => @app.id, :environment => 'staging' | 137 | + get :show, :id => app.id, :environment => 'staging' |
121 | controller.problems.size.should == 5 | 138 | controller.problems.size.should == 5 |
122 | end | 139 | end |
123 | end | 140 | end |
124 | 141 | ||
125 | context 'environment development' do | 142 | context 'environment development' do |
126 | it 'shows errs for just development' do | 143 | it 'shows errs for just development' do |
127 | - get :show, :id => @app.id, :environment => 'development' | 144 | + get :show, :id => app.id, :environment => 'development' |
128 | controller.problems.size.should == 5 | 145 | controller.problems.size.should == 5 |
129 | end | 146 | end |
130 | end | 147 | end |
131 | 148 | ||
132 | context 'environment test' do | 149 | context 'environment test' do |
133 | it 'shows errs for just test' do | 150 | it 'shows errs for just test' do |
134 | - get :show, :id => @app.id, :environment => 'test' | 151 | + get :show, :id => app.id, :environment => 'test' |
135 | controller.problems.size.should == 5 | 152 | controller.problems.size.should == 5 |
136 | end | 153 | end |
137 | end | 154 | end |
@@ -140,9 +157,7 @@ describe AppsController do | @@ -140,9 +157,7 @@ describe AppsController do | ||
140 | 157 | ||
141 | context 'logged in as a user' do | 158 | context 'logged in as a user' do |
142 | it 'finds the app if the user is watching it' do | 159 | it 'finds the app if the user is watching it' do |
143 | - user = Fabricate(:user) | ||
144 | - app = Fabricate(:app) | ||
145 | - watcher = Fabricate(:user_watcher, :app => app, :user => user) | 160 | + watcher |
146 | sign_in user | 161 | sign_in user |
147 | get :show, :id => app.id | 162 | get :show, :id => app.id |
148 | controller.app.should == app | 163 | controller.app.should == app |
@@ -160,7 +175,7 @@ describe AppsController do | @@ -160,7 +175,7 @@ describe AppsController do | ||
160 | 175 | ||
161 | context 'logged in as an admin' do | 176 | context 'logged in as an admin' do |
162 | before do | 177 | before do |
163 | - sign_in Fabricate(:admin) | 178 | + sign_in admin |
164 | end | 179 | end |
165 | 180 | ||
166 | describe "GET /apps/new" do | 181 | describe "GET /apps/new" do |
@@ -345,6 +360,34 @@ describe AppsController do | @@ -345,6 +360,34 @@ describe AppsController do | ||
345 | end | 360 | end |
346 | end | 361 | end |
347 | 362 | ||
363 | + describe "POST /apps/:id/regenerate_api_key" do | ||
364 | + | ||
365 | + context "like watcher" do | ||
366 | + before do | ||
367 | + sign_in watcher.user | ||
368 | + end | ||
369 | + | ||
370 | + it 'redirect to root with flash error' do | ||
371 | + post :regenerate_api_key, :id => 'foo' | ||
372 | + expect(request).to redirect_to root_path | ||
373 | + end | ||
374 | + | ||
375 | + end | ||
376 | + | ||
377 | + context "like admin" do | ||
378 | + before do | ||
379 | + sign_in admin | ||
380 | + end | ||
381 | + | ||
382 | + it 'redirect_to app view' do | ||
383 | + expect do | ||
384 | + post :regenerate_api_key, :id => app.id | ||
385 | + expect(request).to redirect_to edit_app_path(app) | ||
386 | + end.to change { app.api_key } | ||
387 | + end | ||
388 | + end | ||
389 | + | ||
390 | + end | ||
348 | 391 | ||
349 | end | 392 | end |
350 | 393 |
spec/fabricators/err_fabricator.rb
@@ -21,3 +21,4 @@ Fabricator :backtrace_line do | @@ -21,3 +21,4 @@ Fabricator :backtrace_line do | ||
21 | file { "/path/to/file/#{SecureRandom.hex(4)}.rb" } | 21 | file { "/path/to/file/#{SecureRandom.hex(4)}.rb" } |
22 | method(:method) { ActiveSupport.methods.shuffle.first } | 22 | method(:method) { ActiveSupport.methods.shuffle.first } |
23 | end | 23 | end |
24 | + |
spec/fabricators/problem_fabricator.rb
@@ -21,4 +21,10 @@ Fabricator(:problem_with_errs, :from => :problem) do | @@ -21,4 +21,10 @@ Fabricator(:problem_with_errs, :from => :problem) do | ||
21 | } | 21 | } |
22 | end | 22 | end |
23 | 23 | ||
24 | - | 24 | +Fabricator(:problem_resolved, :from => :problem) do |
25 | + after_create do |pr| | ||
26 | + Fabricate(:notice, | ||
27 | + :err => Fabricate(:err, :problem => pr)) | ||
28 | + pr.resolve! | ||
29 | + end | ||
30 | +end |