mirror of
https://github.com/astuto/astuto.git
synced 2025-12-15 11:17:49 +01:00
Add admin panel and make it work for user resource
This commit is contained in:
4
Gemfile
4
Gemfile
@@ -28,8 +28,12 @@ gem 'jbuilder', '~> 2.7'
|
||||
# Reduces boot times through caching; required in config/boot.rb
|
||||
gem 'bootsnap', '>= 1.4.2', require: false
|
||||
|
||||
# Authentication
|
||||
gem 'devise', git: 'https://github.com/plataformatec/devise'
|
||||
|
||||
# Administration panel
|
||||
gem "administrate", git: "https://github.com/thoughtbot/administrate.git"
|
||||
|
||||
group :development, :test do
|
||||
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
||||
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
|
||||
|
||||
50
Gemfile.lock
50
Gemfile.lock
@@ -9,6 +9,23 @@ GIT
|
||||
responders
|
||||
warden (~> 1.2.3)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/thoughtbot/administrate.git
|
||||
revision: fcf46ae4e6989ceb1b091791fec754a67da0f32c
|
||||
specs:
|
||||
administrate (0.11.0)
|
||||
actionpack (>= 4.2)
|
||||
actionview (>= 4.2)
|
||||
activejob (>= 4.2)
|
||||
activerecord (>= 4.2)
|
||||
autoprefixer-rails (>= 6.0)
|
||||
datetime_picker_rails (~> 0.0.7)
|
||||
jquery-rails (>= 4.0)
|
||||
kaminari (>= 1.0)
|
||||
momentjs-rails (~> 2.8)
|
||||
sassc-rails (~> 2.1)
|
||||
selectize-rails (~> 0.6)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
@@ -69,6 +86,8 @@ GEM
|
||||
zeitwerk (~> 2.1, >= 2.1.8)
|
||||
addressable (2.6.0)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
autoprefixer-rails (9.6.1)
|
||||
execjs
|
||||
bcrypt (3.1.13)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.4.4)
|
||||
@@ -87,8 +106,11 @@ GEM
|
||||
rake (< 13.0)
|
||||
concurrent-ruby (1.1.5)
|
||||
crass (1.0.4)
|
||||
datetime_picker_rails (0.0.7)
|
||||
momentjs-rails (>= 2.8.1)
|
||||
diff-lcs (1.3)
|
||||
erubi (1.8.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (5.0.2)
|
||||
activesupport (>= 4.2.0)
|
||||
factory_bot_rails (5.0.2)
|
||||
@@ -101,6 +123,22 @@ GEM
|
||||
concurrent-ruby (~> 1.0)
|
||||
jbuilder (2.9.1)
|
||||
activesupport (>= 4.2.0)
|
||||
jquery-rails (4.3.5)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
kaminari (1.1.1)
|
||||
activesupport (>= 4.1.0)
|
||||
kaminari-actionview (= 1.1.1)
|
||||
kaminari-activerecord (= 1.1.1)
|
||||
kaminari-core (= 1.1.1)
|
||||
kaminari-actionview (1.1.1)
|
||||
actionview
|
||||
kaminari-core (= 1.1.1)
|
||||
kaminari-activerecord (1.1.1)
|
||||
activerecord
|
||||
kaminari-core (= 1.1.1)
|
||||
kaminari-core (1.1.1)
|
||||
listen (3.1.5)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
@@ -117,6 +155,8 @@ GEM
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
minitest (5.11.3)
|
||||
momentjs-rails (2.20.1)
|
||||
railties (>= 3.1)
|
||||
msgpack (1.3.1)
|
||||
nio4r (2.4.0)
|
||||
nokogiri (1.10.4)
|
||||
@@ -194,6 +234,15 @@ GEM
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
sassc (2.1.0)
|
||||
ffi (~> 1.9)
|
||||
sassc-rails (2.1.2)
|
||||
railties (>= 4.0.0)
|
||||
sassc (>= 2.0)
|
||||
sprockets (> 3.0)
|
||||
sprockets-rails
|
||||
tilt
|
||||
selectize-rails (0.12.6)
|
||||
selenium-webdriver (3.142.3)
|
||||
childprocess (>= 0.5, < 2.0)
|
||||
rubyzip (~> 1.2, >= 1.2.2)
|
||||
@@ -242,6 +291,7 @@ PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
administrate!
|
||||
bootsnap (>= 1.4.2)
|
||||
byebug
|
||||
capybara (>= 2.15)
|
||||
|
||||
31
app/controllers/admin/application_controller.rb
Normal file
31
app/controllers/admin/application_controller.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
# All Administrate controllers inherit from this `Admin::ApplicationController`,
|
||||
# making it the ideal place to put authentication logic or other
|
||||
# before_actions.
|
||||
#
|
||||
# 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_action :authenticate_admin
|
||||
|
||||
def authenticate_admin
|
||||
unless user_signed_in?
|
||||
flash[:alert] = "You must be logged in to access this page."
|
||||
redirect_to new_user_session_path
|
||||
return
|
||||
end
|
||||
|
||||
unless current_user.moderator? || current_user.admin?
|
||||
flash[:alert] = "You do not have the privilegies to access this page."
|
||||
redirect_to root_path
|
||||
return
|
||||
end
|
||||
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
|
||||
88
app/controllers/admin/users_controller.rb
Normal file
88
app/controllers/admin/users_controller.rb
Normal file
@@ -0,0 +1,88 @@
|
||||
module Admin
|
||||
class UsersController < Admin::ApplicationController
|
||||
# Overwrite any of the RESTful controller actions to implement custom behavior
|
||||
# For example, you may want to send an email after a foo is updated.
|
||||
#
|
||||
# def update
|
||||
# foo = Foo.find(params[:id])
|
||||
# foo.update(params[:foo])
|
||||
# send_foo_updated_email
|
||||
# end
|
||||
|
||||
# Override this method to specify custom lookup behavior.
|
||||
# This will be used to set the resource for the `show`, `edit`, and `update`
|
||||
# actions.
|
||||
#
|
||||
# def find_resource(param)
|
||||
# Foo.find_by!(slug: param)
|
||||
# end
|
||||
|
||||
# Override this if you have certain roles that require a subset
|
||||
# this will be used to set the records shown on the `index` action.
|
||||
#
|
||||
# def scoped_resource
|
||||
# if current_user.super_admin?
|
||||
# resource_class
|
||||
# else
|
||||
# resource_class.with_less_stuff
|
||||
# end
|
||||
# end
|
||||
|
||||
# See https://administrate-prototype.herokuapp.com/customizing_controller_actions
|
||||
# for more information
|
||||
|
||||
def authenticate_admin
|
||||
super # apply the generic rules for authentication in the admin panel...
|
||||
|
||||
# ...plus this one
|
||||
unless current_user.admin?
|
||||
flash[:alert] = "You do not have the privilegies to access this page."
|
||||
redirect_to root_path
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# overwrite default create
|
||||
def create
|
||||
user = User.new(user_params)
|
||||
user.skip_confirmation! # automatically confirm user email
|
||||
|
||||
if user.save
|
||||
flash[:notice] = translate_with_resource("create.success")
|
||||
redirect_to admin_user_path(user)
|
||||
else
|
||||
render :new, locals: {
|
||||
page: Administrate::Page::Form.new(dashboard, user),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# overwrite default update
|
||||
def update
|
||||
user = User.find(params[:user][:id])
|
||||
|
||||
if params[:user][:password].empty?
|
||||
user.assign_attributes(user_params.except(:password))
|
||||
else
|
||||
user.assign_attributes(user_params)
|
||||
end
|
||||
|
||||
user.skip_reconfirmation! # automatically reconfirm user email
|
||||
|
||||
if user.save
|
||||
flash[:notice] = translate_with_resource("update.success")
|
||||
redirect_to admin_user_path(user)
|
||||
else
|
||||
render :new, locals: {
|
||||
page: Administrate::Page::Form.new(dashboard, user),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:full_name, :email, :role, :password)
|
||||
end
|
||||
end
|
||||
end
|
||||
83
app/dashboards/user_dashboard.rb
Normal file
83
app/dashboards/user_dashboard.rb
Normal file
@@ -0,0 +1,83 @@
|
||||
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: IdField,
|
||||
email: Field::String,
|
||||
password: Field::Password,
|
||||
encrypted_password: Field::String,
|
||||
reset_password_token: Field::String,
|
||||
reset_password_sent_at: Field::DateTime,
|
||||
remember_created_at: Field::DateTime,
|
||||
confirmation_token: Field::String,
|
||||
confirmed_at: Field::DateTime,
|
||||
confirmation_sent_at: Field::DateTime,
|
||||
unconfirmed_email: Field::String,
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime,
|
||||
role: RoleField,
|
||||
full_name: Field::String,
|
||||
}.freeze
|
||||
|
||||
# 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 = %i[
|
||||
full_name
|
||||
email
|
||||
role
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's show page.
|
||||
SHOW_PAGE_ATTRIBUTES = %i[
|
||||
id
|
||||
full_name
|
||||
email
|
||||
role
|
||||
password
|
||||
created_at
|
||||
updated_at
|
||||
confirmed_at
|
||||
confirmation_sent_at
|
||||
unconfirmed_email
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
# an array of attributes that will be displayed
|
||||
# on the model's form (`new` and `edit`) pages.
|
||||
FORM_ATTRIBUTES = %i[
|
||||
id
|
||||
full_name
|
||||
email
|
||||
role
|
||||
password
|
||||
].freeze
|
||||
|
||||
# COLLECTION_FILTERS
|
||||
# a hash that defines filters that can be used while searching via the search
|
||||
# field of the dashboard.
|
||||
#
|
||||
# For example to add an option to search for open resources by typing "open:"
|
||||
# in the search field:
|
||||
#
|
||||
# COLLECTION_FILTERS = {
|
||||
# open: ->(resources) { where(open: true) }
|
||||
# }.freeze
|
||||
COLLECTION_FILTERS = {}.freeze
|
||||
|
||||
# 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
|
||||
7
app/fields/id_field.rb
Normal file
7
app/fields/id_field.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
require "administrate/field/base"
|
||||
|
||||
class IdField < Administrate::Field::Base
|
||||
def to_s
|
||||
data.to_s
|
||||
end
|
||||
end
|
||||
13
app/fields/role_field.rb
Normal file
13
app/fields/role_field.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require "administrate/field/base"
|
||||
|
||||
class RoleField < Administrate::Field::Base
|
||||
def to_s
|
||||
data.to_s
|
||||
end
|
||||
|
||||
def select_field_values(form_builder)
|
||||
form_builder.object.class.public_send(attribute.to_s.pluralize).keys.map do |v|
|
||||
[v.titleize, v]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,8 @@
|
||||
class User < ApplicationRecord
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :validatable,
|
||||
:confirmable
|
||||
|
||||
enum role: [:user, :moderator, :admin]
|
||||
after_initialize :set_default_role, if: :new_record?
|
||||
|
||||
@@ -12,8 +16,4 @@ class User < ApplicationRecord
|
||||
gravatar_id = Digest::MD5::hexdigest(email.downcase)
|
||||
"https://secure.gravatar.com/avatar/#{gravatar_id}"
|
||||
end
|
||||
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :validatable,
|
||||
:confirmable
|
||||
end
|
||||
|
||||
19
app/views/admin/application/_navigation.html.erb
Normal file
19
app/views/admin/application/_navigation.html.erb
Normal file
@@ -0,0 +1,19 @@
|
||||
<%#
|
||||
# Navigation
|
||||
|
||||
This partial is used to display the navigation in Administrate.
|
||||
By default, the navigation contains navigation links
|
||||
for all resources in the admin dashboard,
|
||||
as defined by the routes in the `admin/` namespace
|
||||
%>
|
||||
|
||||
<nav class="navigation" role="navigation">
|
||||
<%= link_to "⇦ Back to site", root_path, class: "navigation__link", "data-turbolinks": "false" %>
|
||||
<% Administrate::Namespace.new(namespace).resources.each do |resource| %>
|
||||
<%= link_to(
|
||||
display_resource_name(resource),
|
||||
[namespace, resource_index_route_key(resource)],
|
||||
class: "navigation__link navigation__link--#{nav_link_state(resource)}"
|
||||
) %>
|
||||
<% end %>
|
||||
</nav>
|
||||
1
app/views/fields/id_field/_form.html.erb
Normal file
1
app/views/fields/id_field/_form.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= f.text_field field.attribute, hidden: :true %>
|
||||
1
app/views/fields/id_field/_index.html.erb
Normal file
1
app/views/fields/id_field/_index.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= field.to_s %>
|
||||
1
app/views/fields/id_field/_show.html.erb
Normal file
1
app/views/fields/id_field/_show.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= field.to_s %>
|
||||
6
app/views/fields/role_field/_form.html.erb
Normal file
6
app/views/fields/role_field/_form.html.erb
Normal file
@@ -0,0 +1,6 @@
|
||||
<div class="field-unit__label">
|
||||
<%= f.label field.attribute %>
|
||||
</div>
|
||||
<div class="field-unit__field">
|
||||
<%= f.select field.attribute, field.select_field_values(f) %>
|
||||
</div>
|
||||
1
app/views/fields/role_field/_index.html.erb
Normal file
1
app/views/fields/role_field/_index.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= field.to_s.titleize %>
|
||||
1
app/views/fields/role_field/_show.html.erb
Normal file
1
app/views/fields/role_field/_show.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= field.to_s.titleize %>
|
||||
@@ -8,6 +8,11 @@
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<% if user_signed_in? %>
|
||||
<% if current_user.moderator? || current_user.admin? %>
|
||||
<li class="nav-item">
|
||||
<%= link_to "Admin Panel", admin_root_path, class: "nav-link", 'data-turbolinks': 'false' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<%= image_tag(current_user.gravatar_url, class: "gravatar", alt: current_user.full_name, size: 24) %>
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
Rails.application.routes.draw do
|
||||
root to: 'static_pages#home'
|
||||
|
||||
namespace :admin do
|
||||
root to: "users#index"
|
||||
resources :users
|
||||
end
|
||||
|
||||
devise_for :users
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user