From a018c42e0fa6baa5cd99b095192e9b10e30530e3 Mon Sep 17 00:00:00 2001 From: Jared Cosulich Date: Wed, 5 Apr 2017 21:17:27 -0400 Subject: [PATCH] working on authentication --- app/controllers/application_controller.rb | 2 +- app/controllers/schools_controller.rb | 17 ++-- app/controllers/users_controller.rb | 17 ++++ app/models/user.rb | 11 +++ app/models/user_school.rb | 7 ++ app/views/schools/admin.html.haml | 2 +- app/views/schools/index.html.haml | 17 ---- app/views/schools/index.json.jbuilder | 4 - app/views/users/show.html.haml | 19 +++++ config/routes.rb | 3 + .../20170405183356_create_user_schools.rb | 11 +++ db/schema.rb | 10 ++- spec/controllers/schools_controller_spec.rb | 82 ++++++++++++------- spec/models/user_school_spec.rb | 5 ++ spec/spec_helper.rb | 1 + spec/support/devise.rb | 4 + spec/views/schools/index.html.erb_spec.rb | 22 ----- 17 files changed, 154 insertions(+), 80 deletions(-) create mode 100644 app/controllers/users_controller.rb create mode 100644 app/models/user_school.rb delete mode 100644 app/views/schools/index.html.haml delete mode 100644 app/views/schools/index.json.jbuilder create mode 100644 app/views/users/show.html.haml create mode 100644 db/migrate/20170405183356_create_user_schools.rb create mode 100644 spec/models/user_school_spec.rb create mode 100644 spec/support/devise.rb delete mode 100644 spec/views/schools/index.html.erb_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c07694e..0b078c31 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,3 @@ class ApplicationController < ActionController::Base - protect_from_forgery with: :exception + protect_from_forgery with: :exception, prepend: true end diff --git a/app/controllers/schools_controller.rb b/app/controllers/schools_controller.rb index 941f6e54..ddf29410 100644 --- a/app/controllers/schools_controller.rb +++ b/app/controllers/schools_controller.rb @@ -1,11 +1,8 @@ class SchoolsController < ApplicationController + before_action :authenticate_user!, except: [:show] before_action :set_school, only: [:admin, :show, :edit, :update, :destroy] + before_action :verify_admin, except: [:show, :create, :new] - # GET /schools - # GET /schools.json - def index - @schools = School.all - end # GET /schools/1 # GET /schools/1.json @@ -13,6 +10,9 @@ class SchoolsController < ApplicationController @school_categories = @school.school_categories.for_parent_category(@school, nil).sort end + def admin + end + # GET /schools/new def new @school = School.new @@ -72,4 +72,11 @@ class SchoolsController < ApplicationController def school_params params.require(:school).permit(:name, :district_id) end + + def verify_admin + return true if current_user.admin?(@school) + + redirect_to root_path, notice: 'You must be logged in as an admin of that school to access that page.' + return false + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 00000000..c22a8f36 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,17 @@ +class UsersController < ApplicationController + + def show + end + + + # private + # # Use callbacks to share common setup or constraints between actions. + # def set_district + # @district = District.find(params[:id]) + # end + # + # # Never trust parameters from the scary internet, only allow the white list through. + # def district_params + # params.require(:district).permit(:name, :state_id) + # end +end diff --git a/app/models/user.rb b/app/models/user.rb index b2091f9a..69e24d25 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,4 +3,15 @@ class User < ApplicationRecord # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable + + has_many :user_schools + + def schools + districts = user_schools.map(&:district).compact.uniq + (user_schools.map(&:school) + districts.map(&:schools)).flatten.compact.uniq + end + + def admin?(school) + schools.index(school).present? + end end diff --git a/app/models/user_school.rb b/app/models/user_school.rb new file mode 100644 index 00000000..fe21ea8b --- /dev/null +++ b/app/models/user_school.rb @@ -0,0 +1,7 @@ +class UserSchool < ApplicationRecord + + belongs_to :user + belongs_to :school + belongs_to :district + +end diff --git a/app/views/schools/admin.html.haml b/app/views/schools/admin.html.haml index e2589773..e4ce1c1d 100644 --- a/app/views/schools/admin.html.haml +++ b/app/views/schools/admin.html.haml @@ -65,7 +65,7 @@ %tbody %thead{style: 'font-weight: bold;'} %th Name - %th Descriptin + %th Description %th{colspan: 2} Actions - @school.recipient_lists.each do |recipient_list| %tr.recipient diff --git a/app/views/schools/index.html.haml b/app/views/schools/index.html.haml deleted file mode 100644 index 53fe1f8b..00000000 --- a/app/views/schools/index.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -%h1 Schools -%table - %thead - %tr - %th Name - %th District - %th{:colspan => "3"} - %tbody - - @schools.each do |school| - %tr - %td= school.name - %td= school.district_id - %td= link_to 'Show', school - %td= link_to 'Edit', edit_school_path(school) - %td= link_to 'Destroy', school, method: :delete, data: { confirm: 'Are you sure?' } -%br/ -= link_to 'New School', new_school_path diff --git a/app/views/schools/index.json.jbuilder b/app/views/schools/index.json.jbuilder deleted file mode 100644 index 507de846..00000000 --- a/app/views/schools/index.json.jbuilder +++ /dev/null @@ -1,4 +0,0 @@ -json.array!(@schools) do |school| - json.extract! school, :id, :name, :district_id - json.url school_url(school, format: :json) -end diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml new file mode 100644 index 00000000..2e7f658d --- /dev/null +++ b/app/views/users/show.html.haml @@ -0,0 +1,19 @@ +%h2.text-center= current_user.email + +%br +%br +%br +%h3 Schools +- if current_user.schools.blank? + %p + %strong None Yet +- else + %table{style: 'width: 100%;'} + %tbody + %thead{style: 'font-weight: bold;'} + %th Name + %th{colspan: 2} + - current_user.schools.each do |school| + %tr.school + %td= link_to school.name, school + %td= link_to('Admin', school_admin_path(school)) diff --git a/config/routes.rb b/config/routes.rb index 14c2eb6e..451e5d80 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,6 +21,9 @@ Rails.application.routes.draw do # resources :attempts, only: [:get, :update] devise_for :users + as :user do + get 'users', :to => 'users#show', :as => :user_root # Rails 3 + end # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html get '/admin', to: 'admin#index', as: 'admin' diff --git a/db/migrate/20170405183356_create_user_schools.rb b/db/migrate/20170405183356_create_user_schools.rb new file mode 100644 index 00000000..576b989c --- /dev/null +++ b/db/migrate/20170405183356_create_user_schools.rb @@ -0,0 +1,11 @@ +class CreateUserSchools < ActiveRecord::Migration[5.0] + def change + create_table :user_schools do |t| + t.integer :user_id + t.integer :school_id + t.integer :district_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 6f4d4ca8..5771af68 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170317150205) do +ActiveRecord::Schema.define(version: 20170405183356) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -152,6 +152,14 @@ ActiveRecord::Schema.define(version: 20170317150205) do t.index ["slug"], name: "index_schools_on_slug", unique: true, using: :btree end + create_table "user_schools", force: :cascade do |t| + t.integer "user_id" + t.integer "school_id" + t.integer "district_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false diff --git a/spec/controllers/schools_controller_spec.rb b/spec/controllers/schools_controller_spec.rb index 7442e17f..de802238 100644 --- a/spec/controllers/schools_controller_spec.rb +++ b/spec/controllers/schools_controller_spec.rb @@ -20,6 +20,10 @@ require 'rails_helper' RSpec.describe SchoolsController, type: :controller do + let!(:school) { School.create(name: 'school') } + let!(:user) { User.create(email: 'test@example.com', password: '123456') } + let!(:user_school) { user.user_schools.create(school: school) } + # This should return the minimal set of attributes required to create a valid # School. As you add validations to School, be sure to # adjust the attributes here as well. @@ -36,14 +40,6 @@ RSpec.describe SchoolsController, type: :controller do # SchoolsController. Be sure to keep this updated too. let(:valid_session) { {} } - describe "GET #index" do - it "assigns all schools as @schools" do - school = School.create! valid_attributes - get :index, params: {}, session: valid_session - expect(assigns(:schools)).to eq([school]) - end - end - describe "GET #show" do it "assigns the requested school as @school" do school = School.create! valid_attributes @@ -54,104 +50,132 @@ RSpec.describe SchoolsController, type: :controller do describe "GET #new" do it "assigns a new school as @school" do - get :new, params: {}, session: valid_session + sign_in user + get :new, params: {} expect(assigns(:school)).to be_a_new(School) end end describe "GET #edit" do it "assigns the requested school as @school" do + sign_in user school = School.create! valid_attributes - get :edit, params: {id: school.to_param}, session: valid_session + get :edit, params: {id: school.to_param} expect(assigns(:school)).to eq(school) end end + describe "GET #admin" do + it "assigns the requested school as @school" do + sign_in user + get :admin, params: {school_id: school.to_param} + expect(assigns(:school)).to eq(school) + end + + it "redirects if not logged in" do + get :admin, params: {school_id: school.to_param} + expect(response).to redirect_to(new_user_session_path) + end + + it "redirects if user is not associated with school" do + another_user = User.create(email: 'test2@test.com', password: '123456') + sign_in another_user + + get :admin, params: {school_id: school.to_param} + expect(response).to redirect_to(root_path) + end + end + describe "POST #create" do + before :each do + sign_in user + end + context "with valid params" do it "creates a new School" do expect { - post :create, params: {school: valid_attributes}, session: valid_session + post :create, params: {school: valid_attributes} }.to change(School, :count).by(1) end it "assigns a newly created school as @school" do - post :create, params: {school: valid_attributes}, session: valid_session + post :create, params: {school: valid_attributes} expect(assigns(:school)).to be_a(School) expect(assigns(:school)).to be_persisted end it "redirects to the created school" do - post :create, params: {school: valid_attributes}, session: valid_session + post :create, params: {school: valid_attributes} expect(response).to redirect_to(School.last) end end context "with invalid params" do it "assigns a newly created but unsaved school as @school" do - post :create, params: {school: invalid_attributes}, session: valid_session + post :create, params: {school: invalid_attributes} expect(assigns(:school)).to be_a_new(School) end it "re-renders the 'new' template" do - post :create, params: {school: invalid_attributes}, session: valid_session + post :create, params: {school: invalid_attributes} expect(response).to render_template("new") end end end describe "PUT #update" do + before :each do + sign_in user + end + context "with valid params" do let(:new_attributes) { {name: 'New School'} } it "updates the requested school" do - school = School.create! valid_attributes - put :update, params: {id: school.to_param, school: new_attributes}, session: valid_session + put :update, params: {id: school.to_param, school: new_attributes} school.reload expect(school.name).to eq('New School') end it "assigns the requested school as @school" do - school = School.create! valid_attributes - put :update, params: {id: school.to_param, school: valid_attributes}, session: valid_session + put :update, params: {id: school.to_param, school: valid_attributes} expect(assigns(:school)).to eq(school) end it "redirects to the school" do - school = School.create! valid_attributes - put :update, params: {id: school.to_param, school: valid_attributes}, session: valid_session + put :update, params: {id: school.to_param, school: valid_attributes} expect(response).to redirect_to(school) end end context "with invalid params" do it "assigns the school as @school" do - school = School.create! valid_attributes - put :update, params: {id: school.to_param, school: invalid_attributes}, session: valid_session + put :update, params: {id: school.to_param, school: invalid_attributes} expect(assigns(:school)).to eq(school) end it "re-renders the 'edit' template" do - school = School.create! valid_attributes - put :update, params: {id: school.to_param, school: invalid_attributes}, session: valid_session + put :update, params: {id: school.to_param, school: invalid_attributes} expect(response).to render_template("edit") end end end describe "DELETE #destroy" do + before :each do + sign_in user + end + it "destroys the requested school" do - school = School.create! valid_attributes expect { - delete :destroy, params: {id: school.to_param}, session: valid_session + delete :destroy, params: {id: school.to_param} }.to change(School, :count).by(-1) end it "redirects to the schools list" do - school = School.create! valid_attributes - delete :destroy, params: {id: school.to_param}, session: valid_session + delete :destroy, params: {id: school.to_param} expect(response).to redirect_to(schools_url) end end diff --git a/spec/models/user_school_spec.rb b/spec/models/user_school_spec.rb new file mode 100644 index 00000000..b6599ad5 --- /dev/null +++ b/spec/models/user_school_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe UserSchool, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5966aa45..a0f32982 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -104,6 +104,7 @@ RSpec.configure do |config| config.after(:each) do FakeSMS.reset end + end diff --git a/spec/support/devise.rb b/spec/support/devise.rb new file mode 100644 index 00000000..0cf56ea8 --- /dev/null +++ b/spec/support/devise.rb @@ -0,0 +1,4 @@ +RSpec.configure do |config| + config.include Devise::Test::ControllerHelpers, type: :controller + config.include Devise::Test::ControllerHelpers, type: :view +end diff --git a/spec/views/schools/index.html.erb_spec.rb b/spec/views/schools/index.html.erb_spec.rb deleted file mode 100644 index 0ee5886c..00000000 --- a/spec/views/schools/index.html.erb_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'rails_helper' - -RSpec.describe "schools/index", type: :view do - before(:each) do - assign(:schools, [ - School.create!( - :name => "Name", - :district_id => 2 - ), - School.create!( - :name => "Name", - :district_id => 2 - ) - ]) - end - - it "renders a list of schools" do - render - assert_select "tr>td", :text => "Name".to_s, :count => 2 - assert_select "tr>td", :text => 2.to_s, :count => 2 - end -end