diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb new file mode 100644 index 0000000..8d5684d --- /dev/null +++ b/app/controllers/admin/application_controller.rb @@ -0,0 +1,21 @@ +# All Administrate controllers inherit from this `Admin::ApplicationController`, +# making it the ideal place to put authentication logic or other +# before_filters. +# +# If you want to add pagination or other controller-level concerns, +# you're free to overwrite the RESTful controller actions. +module Admin + class ApplicationController < Administrate::ApplicationController + before_filter :authenticate_admin + + def authenticate_admin + # TODO Add authentication logic here. + end + + # Override this value to specify the number of elements to display at a time + # on index pages. Defaults to 20. + # def records_per_page + # params[:per_page] || 20 + # end + end +end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb new file mode 100644 index 0000000..43795c3 --- /dev/null +++ b/app/controllers/admin/users_controller.rb @@ -0,0 +1,19 @@ +module Admin + class UsersController < Admin::ApplicationController + # To customize the behavior of this controller, + # simply overwrite any of the RESTful actions. For example: + # + # def index + # super + # @resources = User.all.paginate(10, params[:page]) + # end + + # Define a custom finder by overriding the `find_resource` method: + # def find_resource(param) + # User.find_by!(slug: param) + # end + + # See https://administrate-docs.herokuapp.com/customizing_controller_actions + # for more information + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000..4c2ea89 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,38 @@ +class UsersController < ApplicationController + before_action :authenticate_user! + after_action :verify_authorized + + def index + @users = User.all + authorize User + end + + def show + @user = User.find(params[:id]) + authorize @user + end + + def update + @user = User.find(params[:id]) + authorize @user + if @user.update_attributes(secure_params) + redirect_to users_path, :notice => "User updated." + else + redirect_to users_path, :alert => "Unable to update user." + end + end + + def destroy + user = User.find(params[:id]) + authorize user + user.destroy + redirect_to users_path, :notice => "User deleted." + end + + private + + def secure_params + params.require(:user).permit(:role) + end + +end diff --git a/app/controllers/visitors_controller.rb b/app/controllers/visitors_controller.rb new file mode 100644 index 0000000..ebe5fb6 --- /dev/null +++ b/app/controllers/visitors_controller.rb @@ -0,0 +1,2 @@ +class VisitorsController < ApplicationController +end diff --git a/app/dashboards/user_dashboard.rb b/app/dashboards/user_dashboard.rb new file mode 100644 index 0000000..09fc6e2 --- /dev/null +++ b/app/dashboards/user_dashboard.rb @@ -0,0 +1,93 @@ +require "administrate/base_dashboard" + +class UserDashboard < Administrate::BaseDashboard + # ATTRIBUTE_TYPES + # a hash that describes the type of each of the model's fields. + # + # Each different type represents an Administrate::Field object, + # which determines how the attribute is displayed + # on pages throughout the dashboard. + ATTRIBUTE_TYPES = { + id: Field::Number, + email: Field::String, + encrypted_password: Field::String, + reset_password_token: Field::String, + reset_password_sent_at: Field::DateTime, + remember_created_at: Field::DateTime, + sign_in_count: Field::Number, + current_sign_in_at: Field::DateTime, + last_sign_in_at: Field::DateTime, + current_sign_in_ip: Field::String, + last_sign_in_ip: Field::String, + created_at: Field::DateTime, + updated_at: Field::DateTime, + name: Field::String, + confirmation_token: Field::String, + confirmed_at: Field::DateTime, + confirmation_sent_at: Field::DateTime, + unconfirmed_email: Field::String, + } + + # COLLECTION_ATTRIBUTES + # an array of attributes that will be displayed on the model's index page. + # + # By default, it's limited to four items to reduce clutter on index pages. + # Feel free to add, remove, or rearrange items. + COLLECTION_ATTRIBUTES = [ + :id, + :email, + :encrypted_password, + :reset_password_token, + ] + + # SHOW_PAGE_ATTRIBUTES + # an array of attributes that will be displayed on the model's show page. + SHOW_PAGE_ATTRIBUTES = [ + :id, + :email, + :encrypted_password, + :reset_password_token, + :reset_password_sent_at, + :remember_created_at, + :sign_in_count, + :current_sign_in_at, + :last_sign_in_at, + :current_sign_in_ip, + :last_sign_in_ip, + :created_at, + :updated_at, + :name, + :confirmation_token, + :confirmed_at, + :confirmation_sent_at, + :unconfirmed_email, + ] + + # FORM_ATTRIBUTES + # an array of attributes that will be displayed + # on the model's form (`new` and `edit`) pages. + FORM_ATTRIBUTES = [ + :email, + :encrypted_password, + :reset_password_token, + :reset_password_sent_at, + :remember_created_at, + :sign_in_count, + :current_sign_in_at, + :last_sign_in_at, + :current_sign_in_ip, + :last_sign_in_ip, + :name, + :confirmation_token, + :confirmed_at, + :confirmation_sent_at, + :unconfirmed_email, + ] + + # Overwrite this method to customize how users are displayed + # across all pages of the admin dashboard. + # + # def display_resource(user) + # "User ##{user.id}" + # end +end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb new file mode 100644 index 0000000..2889a10 --- /dev/null +++ b/app/policies/user_policy.rb @@ -0,0 +1,26 @@ +class UserPolicy + attr_reader :current_user, :model + + def initialize(current_user, model) + @current_user = current_user + @user = model + end + + def index? + @current_user.admin? + end + + def show? + @current_user.admin? or @current_user == @user + end + + def update? + @current_user.admin? + end + + def destroy? + return false if @current_user == @user + @current_user.admin? + end + +end diff --git a/app/views/pages/about.html.erb b/app/views/pages/about.html.erb new file mode 100644 index 0000000..996fa0c --- /dev/null +++ b/app/views/pages/about.html.erb @@ -0,0 +1,7 @@ +<% content_for :title do %>About<% end %> +

About the Website

+

+This web application was created with +<%= link_to('Rails Composer', 'http://railsapps.github.io/rails-composer/') %> +from the <%= link_to('RailsApps project', 'http://railsapps.github.io/') %>. +

diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb new file mode 100644 index 0000000..f1a3d7c --- /dev/null +++ b/app/views/users/_user.html.erb @@ -0,0 +1,12 @@ + + <%= link_to user.email, user %> + + + <%= form_for(user) do |f| %> + <%= f.select(:role, User.roles.keys.map {|role| [role.titleize,role]}) %> + <%= f.submit 'Change Role', :class => 'button-xs' %> + <% end %> + + + <%= link_to("Delete user", user_path(user), :data => { :confirm => "Are you sure?" }, :method => :delete, :class => 'button-xs') unless user == current_user %> + diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000..1ed37ec --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,16 @@ +
+
+

Users

+
+ + + <% @users.each do |user| %> + + <%= render user %> + + <% end %> + +
+
+
+
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb new file mode 100644 index 0000000..8d0767f --- /dev/null +++ b/app/views/users/show.html.erb @@ -0,0 +1,3 @@ +

User

+

Name: <%= @user.name if @user.name %>

+

Email: <%= @user.email if @user.email %>

diff --git a/app/views/visitors/index.html.erb b/app/views/visitors/index.html.erb new file mode 100644 index 0000000..5854d00 --- /dev/null +++ b/app/views/visitors/index.html.erb @@ -0,0 +1,2 @@ +

Welcome

+

<%= link_to 'Users:', users_path %> <%= User.count %> registered

diff --git a/config/initializers/devise_permitted_parameters.rb b/config/initializers/devise_permitted_parameters.rb new file mode 100644 index 0000000..cbbee2a --- /dev/null +++ b/config/initializers/devise_permitted_parameters.rb @@ -0,0 +1,17 @@ +module DevisePermittedParameters + extend ActiveSupport::Concern + + included do + before_action :configure_permitted_parameters + end + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.for(:sign_up) << :name + devise_parameter_sanitizer.for(:account_update) << :name + end + +end + +DeviseController.send :include, DevisePermittedParameters diff --git a/config/initializers/pundit.rb b/config/initializers/pundit.rb new file mode 100644 index 0000000..f574e12 --- /dev/null +++ b/config/initializers/pundit.rb @@ -0,0 +1,22 @@ +# config/initializers/pundit.rb +# Extends the ApplicationController to add Pundit for authorization. +# Modify this file to change the behavior of a 'not authorized' error. +# Be sure to restart your server when you modify this file. +module PunditHelper + extend ActiveSupport::Concern + + included do + include Pundit + rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized + end + + private + + def user_not_authorized + flash[:alert] = "Access denied." + redirect_to (request.referrer || root_path) + end + +end + +ApplicationController.send :include, PunditHelper diff --git a/config/routes.rb b/config/routes.rb index fc2791d..72c1a65 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,13 @@ Rails.application.routes.draw do + namespace :admin do + resources :users + + root to: "users#index" + end + + root to: 'visitors#index' devise_for :users + resources :users # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". diff --git a/spec/features/visitors/about_page_spec.rb b/spec/features/visitors/about_page_spec.rb new file mode 100644 index 0000000..d94b56d --- /dev/null +++ b/spec/features/visitors/about_page_spec.rb @@ -0,0 +1,16 @@ +# Feature: 'About' page +# As a visitor +# I want to visit an 'about' page +# So I can learn more about the website +feature 'About page' do + + # Scenario: Visit the 'about' page + # Given I am a visitor + # When I visit the 'about' page + # Then I see "About the Website" + scenario 'Visit the about page' do + visit 'pages/about' + expect(page).to have_content 'About the Website' + end + +end diff --git a/spec/features/visitors/home_page_spec.rb b/spec/features/visitors/home_page_spec.rb new file mode 100644 index 0000000..8afa365 --- /dev/null +++ b/spec/features/visitors/home_page_spec.rb @@ -0,0 +1,16 @@ +# Feature: Home page +# As a visitor +# I want to visit a home page +# So I can learn more about the website +feature 'Home page' do + + # Scenario: Visit the home page + # Given I am a visitor + # When I visit the home page + # Then I see "Welcome" + scenario 'visit the home page' do + visit root_path + expect(page).to have_content 'Welcome' + end + +end