From 95c2aa133f22b04dff7fc8b25f2af3edd78a6a84 Mon Sep 17 00:00:00 2001 From: Jared Pace Date: Fri, 13 Aug 2010 14:01:29 -0400 Subject: [PATCH] Scope apps and errs when a regular user is logged in --- README.md | 3 ++- app/controllers/apps_controller.rb | 18 ++++++++++++------ app/controllers/errs_controller.rb | 26 ++++++++++++++++++++------ app/models/app.rb | 3 ++- app/models/err.rb | 1 + app/models/user.rb | 6 +++++- app/views/apps/_fields.html.haml | 2 +- spec/controllers/errs_controller_spec.rb | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------ 8 files changed, 134 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index ba270d8..f48ad69 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,5 @@ TODO Add capistrano Add form.error_messages Add a deployment view -Add ability for watchers to be configured for types of notifications they should receive \ No newline at end of file +Add ability for watchers to be configured for types of notifications they should receive +Differentiate resolved errs \ No newline at end of file diff --git a/app/controllers/apps_controller.rb b/app/controllers/apps_controller.rb index 80b480e..e357d5a 100644 --- a/app/controllers/apps_controller.rb +++ b/app/controllers/apps_controller.rb @@ -1,13 +1,13 @@ class AppsController < ApplicationController before_filter :require_admin!, :except => [:index, :show] + before_filter :find_app, :except => [:index, :new, :create] def index @apps = current_user.admin? ? App.all : current_user.apps.all end def show - @app = current_user.admin? ? App.find(params[:id]) : current_user.apps.find_by_id!(params[:id]) @errs = @app.errs.paginate end @@ -17,7 +17,6 @@ class AppsController < ApplicationController end def edit - @app = App.find(params[:id]) @app.watchers.build if @app.watchers.none? end @@ -32,9 +31,7 @@ class AppsController < ApplicationController end end - def update - @app = App.find(params[:id]) - + def update if @app.update_attributes(params[:app]) flash[:success] = "Good news everyone! '#{@app.name}' was successfully updated." redirect_to app_path(@app) @@ -44,9 +41,18 @@ class AppsController < ApplicationController end def destroy - @app = App.find(params[:id]) @app.destroy flash[:success] = "'#{@app.name}' was successfully destroyed." redirect_to apps_path end + + protected + + def find_app + @app = App.find(params[:id]) + + # Mongoid Bug: could not chain: current_user.apps.find_by_id! + # apparently finding by 'watchers.email' and 'id' is broken + raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app) + end end diff --git a/app/controllers/errs_controller.rb b/app/controllers/errs_controller.rb index a2fd92b..da20167 100644 --- a/app/controllers/errs_controller.rb +++ b/app/controllers/errs_controller.rb @@ -1,23 +1,27 @@ class ErrsController < ApplicationController + before_filter :find_app, :except => [:index, :all] + def index - @errs = Err.unresolved.ordered.paginate(:page => params[:page]) + app_scope = current_user.admin? ? App.all : current_user.apps + @errs = Err.for_apps(app_scope).unresolved.ordered.paginate(:page => params[:page]) end def all - @errs = Err.ordered.paginate(:page => params[:page]) + app_scope = current_user.admin? ? App.all : current_user.apps + @errs = Err.for_apps(app_scope).ordered.paginate(:page => params[:page]) end def show - @app = App.find(params[:app_id]) @err = @app.errs.find(params[:id]) - @notices = @err.notices.ordered.paginate(:page => (params[:notice] || @err.notices.count), :per_page => 1) + page = (params[:notice] || @err.notices.count) + page = 1 if page.zero? + @notices = @err.notices.ordered.paginate(:page => page, :per_page => 1) @notice = @notices.first end def resolve - @app = App.find(params[:app_id]) - @err = @app.errs.unresolved.find(params[:id]) + @err = @app.errs.unresolved.find(params[:id]) # Deal with bug in mogoid where find is returning an Enumberable obj @err = @err.first if @err.respond_to?(:first) @@ -28,4 +32,14 @@ class ErrsController < ApplicationController redirect_to errs_path end + protected + + def find_app + @app = App.find(params[:app_id]) + + # Mongoid Bug: could not chain: current_user.apps.find_by_id! + # apparently finding by 'watchers.email' and 'id' is broken + raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app) + end + end diff --git a/app/models/app.rb b/app/models/app.rb index 316abb0..a05999b 100644 --- a/app/models/app.rb +++ b/app/models/app.rb @@ -22,7 +22,8 @@ class App # Mongoid Bug: find(id) on association proxies returns an Enumerator def self.find_by_id!(app_id) - where(:id => app_id).first || raise(Mongoid::Errors::DocumentNotFound.new(self,key)) + raise app_id.inspect + where(:id => app_id).first || raise(Mongoid::Errors::DocumentNotFound.new(self,app_id)) end def self.find_by_api_key!(key) diff --git a/app/models/err.rb b/app/models/err.rb index c481843..a2e4cd2 100644 --- a/app/models/err.rb +++ b/app/models/err.rb @@ -19,6 +19,7 @@ class Err scope :unresolved, where(:resolved => false) scope :ordered, order_by(:last_notice_at.desc) scope :in_env, lambda {|env| where(:environment => env)} + scope :for_apps, lambda {|apps| where(:app_id.in => apps.all.map(&:id))} def self.for(attrs) app = attrs.delete(:app) diff --git a/app/models/user.rb b/app/models/user.rb index 1962320..18f5013 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -20,7 +20,11 @@ class User end def apps - App.where('watchers.user_id' => id) + App.where('watchers.user_id' => id.to_s) + end + + def watching?(app) + apps.all.include?(app) end protected diff --git a/app/views/apps/_fields.html.haml b/app/views/apps/_fields.html.haml index 69c717f..be51c57 100644 --- a/app/views/apps/_fields.html.haml +++ b/app/views/apps/_fields.html.haml @@ -12,7 +12,7 @@ %div.nested %div = w.label :user - = w.select :user_id, User.all.map{|u| [u.name,u.id]}, :include_blank => '-- Select a User --' + = w.select :user_id, User.all.map{|u| [u.name,u.id.to_s]}, :include_blank => '-- Select a User --' %strong.option - OR - %div = w.label :email diff --git a/spec/controllers/errs_controller_spec.rb b/spec/controllers/errs_controller_spec.rb index e75ef53..7903520 100644 --- a/spec/controllers/errs_controller_spec.rb +++ b/spec/controllers/errs_controller_spec.rb @@ -9,33 +9,59 @@ describe ErrsController do let(:app) { Factory(:app) } let(:err) { Factory(:err, :app => app) } - - before do - sign_in Factory(:user) - end - + describe "GET /errs" do - it "gets a paginated list of unresolved errs" do - errs = WillPaginate::Collection.new(1,30) - 3.times { errs << Factory(:err) } - Err.should_receive(:unresolved).and_return( - mock('proxy', :ordered => mock('proxy', :paginate => errs)) - ) - get :index - assigns(:errs).should == errs + context 'when logged in as an admin' do + it "gets a paginated list of unresolved errs" do + sign_in Factory(:admin) + errs = WillPaginate::Collection.new(1,30) + 3.times { errs << Factory(:err) } + Err.should_receive(:unresolved).and_return( + mock('proxy', :ordered => mock('proxy', :paginate => errs)) + ) + get :index + assigns(:errs).should == errs + end + end + + context 'when logged in as a user' do + it 'gets a paginated list of unresolved errs for the users apps' do + sign_in(user = Factory(:user)) + unwatched_err = Factory(:err) + watched_unresolved_err = Factory(:err, :app => Factory(:watcher, :user => user).app, :resolved => false) + watched_resolved_err = Factory(:err, :app => Factory(:watcher, :user => user).app, :resolved => true) + get :index + assigns(:errs).should include(watched_unresolved_err) + assigns(:errs).should_not include(unwatched_err, watched_resolved_err) + end end end describe "GET /errs/all" do - it "gets a paginated list of all errs" do - errs = WillPaginate::Collection.new(1,30) - 3.times { errs << Factory(:err) } - 3.times { errs << Factory(:err, :resolved => true)} - Err.should_receive(:ordered).and_return( - mock('proxy', :paginate => errs) - ) - get :index - assigns(:errs).should == errs + context 'when logged in as an admin' do + it "gets a paginated list of all errs" do + sign_in Factory(:admin) + errs = WillPaginate::Collection.new(1,30) + 3.times { errs << Factory(:err) } + 3.times { errs << Factory(:err, :resolved => true)} + Err.should_receive(:ordered).and_return( + mock('proxy', :paginate => errs) + ) + get :all + assigns(:errs).should == errs + end + end + + context 'when logged in as a user' do + it 'gets a paginated list of all errs for the users apps' do + sign_in(user = Factory(:user)) + unwatched_err = Factory(:err) + watched_unresolved_err = Factory(:err, :app => Factory(:watcher, :user => user).app, :resolved => false) + watched_resolved_err = Factory(:err, :app => Factory(:watcher, :user => user).app, :resolved => true) + get :all + assigns(:errs).should include(watched_resolved_err, watched_unresolved_err) + assigns(:errs).should_not include(unwatched_err) + end end end @@ -44,28 +70,57 @@ describe ErrsController do 3.times { Factory(:notice, :err => err)} end - it "finds the app" do - get :show, :app_id => app.id, :id => err.id - assigns(:app).should == app - end + context 'when logged in as an admin' do + before do + sign_in Factory(:admin) + end + + it "finds the app" do + get :show, :app_id => app.id, :id => err.id + assigns(:app).should == app + end + + it "finds the err" do + get :show, :app_id => app.id, :id => err.id + assigns(:err).should == err + end - it "finds the err" do - get :show, :app_id => app.id, :id => err.id - assigns(:err).should == err + it "paginates the notices, 1 at a time" do + App.stub(:find).with(app.id).and_return(app) + app.errs.stub(:find).with(err.id).and_return(err) + err.notices.should_receive(:ordered).and_return(proxy = stub('proxy')) + proxy.should_receive(:paginate).with(:page => 3, :per_page => 1). + and_return(WillPaginate::Collection.new(1,1) << err.notices.first) + get :show, :app_id => app.id, :id => err.id + end end - it "paginates the notices, 1 at a time" do - App.stub(:find).with(app.id).and_return(app) - app.errs.stub(:find).with(err.id).and_return(err) - err.notices.should_receive(:ordered).and_return(proxy = stub('proxy')) - proxy.should_receive(:paginate).with(:page => 3, :per_page => 1). - and_return(WillPaginate::Collection.new(1,1) << err.notices.first) - get :show, :app_id => app.id, :id => err.id + context 'when logged in as a user' do + before do + sign_in(@user = Factory(:user)) + @unwatched_err = Factory(:err) + @watched_app = Factory(:app) + @watcher = Factory(:watcher, :user => @user, :app => @watched_app) + @watched_err = Factory(:err, :app => @watched_app) + end + + it 'finds the err if the user is watching the app' do + get :show, :app_id => @watched_app.to_param, :id => @watched_err.id + assigns(:err).should == @watched_err + end + + it 'raises a DocumentNotFound error if the user is not watching the app' do + lambda { + get :show, :app_id => @unwatched_err.app_id, :id => @unwatched_err.id + }.should raise_error(Mongoid::Errors::DocumentNotFound) + end end end describe "PUT /apps/:app_id/errs/:id/resolve" do before do + sign_in Factory(:admin) + @err = Factory(:err) App.stub(:find).with(@err.app.id).and_return(@err.app) @err.app.errs.stub(:unresolved). -- libgit2 0.21.2