Commit 46220c77 by Ngô Trung Hưng

authorize user

parent 58b92a21
Pipeline #1122 failed with stages
in 0 seconds
......@@ -41,6 +41,7 @@ gem 'therubyracer'
gem 'sidekiq'
gem 'devise-async'
gem 'mailcatcher'
gem 'cancancan'
# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'
......
......@@ -62,6 +62,7 @@ GEM
rails (>= 5.0)
builder (3.2.4)
byebug (11.1.3)
cancancan (3.1.0)
capistrano (3.14.1)
airbrussh (>= 1.0.0)
i18n
......@@ -410,6 +411,7 @@ DEPENDENCIES
bootsnap (>= 1.1.0)
breadcrumbs_on_rails
byebug
cancancan
capistrano
capistrano-bundler
capistrano-rails
......
......@@ -15,6 +15,7 @@
//= require activestorage
//= require turbolinks
//= require jquery.min
//= require bootstrap.min
//= require_tree .
toastr.options = {
'closeButton': true,
......
!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return g({type:O.error,iconClass:m().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=m()),v=e("#"+t.containerId),v.length?v:(n&&(v=d(t)),v)}function o(e,t,n){return g({type:O.info,iconClass:m().iconClasses.info,message:e,optionsOverride:n,title:t})}function s(e){C=e}function i(e,t,n){return g({type:O.success,iconClass:m().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return g({type:O.warning,iconClass:m().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e,t){var o=m();v||n(o),u(e,o,t)||l(o)}function c(t){var o=m();return v||n(o),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function l(t){for(var n=v.children(),o=n.length-1;o>=0;o--)u(e(n[o]),t)}function u(t,n,o){var s=!(!o||!o.force)&&o.force;return!(!t||!s&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0)}function d(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'<button type="button">&times;</button>',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function f(e){C&&C(e)}function g(t){function o(e){return null==e&&(e=""),e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&#39;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function s(){c(),u(),d(),p(),g(),C(),l(),i()}function i(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}I.attr("aria-live",e)}function a(){E.closeOnHover&&I.hover(H,D),!E.onclick&&E.tapToDismiss&&I.click(b),E.closeButton&&j&&j.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),E.onCloseClick&&E.onCloseClick(e),b(!0)}),E.onclick&&I.click(function(e){E.onclick(e),b()})}function r(){I.hide(),I[E.showMethod]({duration:E.showDuration,easing:E.showEasing,complete:E.onShown}),E.timeOut>0&&(k=setTimeout(b,E.timeOut),F.maxHideTime=parseFloat(E.timeOut),F.hideEta=(new Date).getTime()+F.maxHideTime,E.progressBar&&(F.intervalId=setInterval(x,10)))}function c(){t.iconClass&&I.addClass(E.toastClass).addClass(y)}function l(){E.newestOnTop?v.prepend(I):v.append(I)}function u(){if(t.title){var e=t.title;E.escapeHtml&&(e=o(t.title)),M.append(e).addClass(E.titleClass),I.append(M)}}function d(){if(t.message){var e=t.message;E.escapeHtml&&(e=o(t.message)),B.append(e).addClass(E.messageClass),I.append(B)}}function p(){E.closeButton&&(j.addClass(E.closeClass).attr("role","button"),I.prepend(j))}function g(){E.progressBar&&(q.addClass(E.progressClass),I.prepend(q))}function C(){E.rtl&&I.addClass("rtl")}function O(e,t){if(e.preventDuplicates){if(t.message===w)return!0;w=t.message}return!1}function b(t){var n=t&&E.closeMethod!==!1?E.closeMethod:E.hideMethod,o=t&&E.closeDuration!==!1?E.closeDuration:E.hideDuration,s=t&&E.closeEasing!==!1?E.closeEasing:E.hideEasing;if(!e(":focus",I).length||t)return clearTimeout(F.intervalId),I[n]({duration:o,easing:s,complete:function(){h(I),clearTimeout(k),E.onHidden&&"hidden"!==P.state&&E.onHidden(),P.state="hidden",P.endTime=new Date,f(P)}})}function D(){(E.timeOut>0||E.extendedTimeOut>0)&&(k=setTimeout(b,E.extendedTimeOut),F.maxHideTime=parseFloat(E.extendedTimeOut),F.hideEta=(new Date).getTime()+F.maxHideTime)}function H(){clearTimeout(k),F.hideEta=0,I.stop(!0,!0)[E.showMethod]({duration:E.showDuration,easing:E.showEasing})}function x(){var e=(F.hideEta-(new Date).getTime())/F.maxHideTime*100;q.width(e+"%")}var E=m(),y=t.iconClass||E.iconClass;if("undefined"!=typeof t.optionsOverride&&(E=e.extend(E,t.optionsOverride),y=t.optionsOverride.iconClass||y),!O(E,t)){T++,v=n(E,!0);var k=null,I=e("<div/>"),M=e("<div/>"),B=e("<div/>"),q=e("<div/>"),j=e(E.closeHtml),F={intervalId:null,hideEta:null,maxHideTime:null},P={toastId:T,state:"visible",startTime:new Date,options:E,map:t};return s(),r(),a(),f(P),E.debug&&console&&console.log(P),I}}function m(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),w=void 0))}var v,C,w,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:c,error:t,getContainer:n,info:o,options:{},subscribe:s,success:i,version:"2.1.3",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
//# sourceMappingURL=toastr.js.map
......@@ -88,6 +88,9 @@
}
}
.pd-b {
margin-bottom: 10px;
}
.avt_user {
text-align: center;
......
// Place all the styles related to the admin/accounts controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
# string_frozen_literal: true
class Admin::AccountsController < ApplicationController
def index
@list_acc = Admin.all
authorize! :index, :accounts
end
def new_account
@account = Admin.new
render :form
end
def create
account = Admin.new(applied_job_params)
if account.save
flash[:success] = 'Thành công'
else
flash[:error] = helpers.render_errors(account)
redirect_to new_accounts_path
end
end
private
def applied_job_params
params.require(:admin).permit(:email, :password, :password_confirmation, :rule_id)
end
end
......@@ -8,11 +8,13 @@ class Admin::AdminController < ApplicationController
include InitApply
def index
authorize! :index, :admin
end
def show_applied
@applied = AppliedJob.includes(:job).all_result.page(params[:page]).per(6)
@apply = apply
authorize! :show_applied, :admin
end
def search
......
......@@ -2,7 +2,9 @@ class Admin::SettingsController < ApplicationController
before_action :authenticate_admin!
before_action :get_list_cronjob
def index; end
def index
authorize! :index, :settings
end
def cron_implement
tmp = File.open(eval(Settings.path_schedule_tmp), 'w')
......
......@@ -20,6 +20,16 @@ class ApplicationController < ActionController::Base
return admin_path if resource.model_name == Admin.name
stored_location_for(resource) || root_path
end
def current_ability
@current_ability ||= current_admin ? Ability.new(current_admin) : Ability.new(current_user)
end
rescue_from CanCan::AccessDenied do |exception|
respond_to do |format|
format.html { redirect_to (user_signed_in? ? root_path : admin_path), alert: exception.message }
end
end
protected
......
# frozen_string_literal: true
class Ability
include CanCan::Ability
def initialize(obj)
if obj.present?
return if obj.is_a?(User)
can :index, :admin
case obj.rule_id
when 'Administrator'
can :show_applied, :admin
can :index, :settings
can :index, :accounts
when 'Manager'
can :show_applied, :admin
can :index, :settings
when 'Saler'
can :show_applied, :admin
end
end
end
end
......@@ -3,4 +3,5 @@ class Admin < ApplicationRecord
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
enum rule_id: %i|Saler Manager Administrator|
end
<div class="container">
<div class="box_form">
<%= form_with(model: @account, url: create_accounts_path) do |f| %>
<div class="row">
<div class="col-lg-12">
<h2 style="text-align: center">Tạo tài khoản</h2><hr>
</div>
<div class="col-md-6">
<%= f.email_field :email, autofocus: true, class: 'form-control', placeholder: 'Tài khoản' %>
</div>
<div class="col-md-6 pd-b">
<%= select_tag :rule_id, options_for_select(Admin.rule_ids), class: 'form-control' %>
</div>
<div class="col-md-6">
<%= f.password_field :password, autocomplete: 'new-password', class: 'form-control', placeholder: 'Mật khẩu' %>
<% if @minimum_password_length %>
<em style="font-size: 15px;">(<%= t('devise.notice_password',minimum_password_length: @minimum_password_length) %>)</em>
<% end %>
</div>
<div class="col-md-6 pd-b">
<%= f.password_field :password_confirmation, autocomplete: 'new-password', class: 'form-control', placeholder: 'Xác nhận mật khẩu' %>
</div>
<div class="col-md-6 offset-md-6">
<%= f.submit t('devise.title_register'), class: 'btn btn-info btn-info-custom' %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<div class="container"><br>
<h3 class="title_setting">Quản lý tài khoản</h3>
<%= link_to "Thêm tài khoản", new_accounts_path, class: 'link_ct' %><hr>
<div class="row">
<div class="col-lg-12">
<table class="table table-dark">
<thead>
<tr>
<th scope="col">Tài khoản</th>
<th scope="col">Ngày tạo</th>
<th scope="col">Level</th>
<th scope="col">Tùy chọn</th>
</tr>
</thead>
<tbody class="tbody_custom">
<% @list_acc.each do |acc| %>
<tr>
<td><%= acc.email %></td>
<td><%= acc.created_at.strftime('%d - %m - %Y') %></td>
<td><%= acc.rule_id %></td>
<td>
<%= link_to 'Đổi mật khẩu', '#' ,method: :get, 'data-admin_id': acc.id, remote: true, class: 'link_ct reset_pass' %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
\ No newline at end of file
......@@ -2,12 +2,19 @@
<div class="box_menu_admin">
<h2>Menu Admin</h2><hr>
<div class="row">
<div class="col-lg-6">
<div class="col-lg-4">
<%= link_to "Danh sách ứng tuyển", applies_index_path, class: 'btn-col-6' %>
</div>
<div class="col-lg-6">
<%= link_to "Cài đặt", settings_path, class: 'btn-col-6' %>
</div>
<% if can? :index, :settings %>
<div class="col-lg-4">
<%= link_to "Cài đặt", settings_path, class: 'btn-col-6' %>
</div>
<% end %>
<% if can? :index, :accounts %>
<div class="col-lg-4">
<%= link_to "Tài khoản", accounts_index_path, class: 'btn-col-6' %>
</div>
<% end %>
</div>
</div>
</div>
......@@ -15,7 +15,7 @@
<%= link_to t('pages.index.signout'), destroy_user_session_path, method: :delete, class: 'link_item_menu_header_right'%>
</li>
<li class="list_item_menu_header_right">
<%= link_to 'Settings', settings_path, class: 'link_item_menu_header_right'%>
<%= link_to 'Chức năng', admin_path, class: 'link_item_menu_header_right'%>
</li>
<% else %>
<li class="list_item_menu_header_right">
......
......@@ -306,5 +306,5 @@ Devise.setup do |config|
# When set to false, does not sign a user in automatically after their password is
# changed. Defaults to true, so a user is signed in automatically after changing a password.
# config.sign_in_after_change_password = true
config.sign_in_after_change_password = false
end
......@@ -13,6 +13,10 @@ Rails.application.routes.draw do
get 'admin/search', to: 'admin/admin#search', as: :applies
get 'admin/applies', to: 'admin/admin#show_applied', as: :applies_index
get 'admin/account', to: 'admin/accounts#index', as: :accounts_index
get 'admin/new_account', to: 'admin/accounts#new_account', as: :new_accounts
post 'admin/create', to: 'admin/accounts#create', as: :create_accounts
get 'info/user/:user_id', to: 'users#personal_page', as: :personal_page
# devise_for :users, controllers: { registrations: 'registrations', passwords: 'passwords'}
......
class AddColumnRuleIdToTableAdmin < ActiveRecord::Migration[5.2]
def change
add_column :admins, :rule_id, :integer
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_09_07_010650) do
ActiveRecord::Schema.define(version: 2020_11_03_084140) do
create_table "admins", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.string "email", default: "", null: false
......@@ -28,6 +28,7 @@ ActiveRecord::Schema.define(version: 2020_09_07_010650) do
t.datetime "locked_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "rule_id"
t.index ["email"], name: "index_admins_on_email", unique: true
t.index ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true
end
......@@ -113,6 +114,13 @@ ActiveRecord::Schema.define(version: 2020_09_07_010650) do
t.datetime "updated_at", null: false
end
create_table "roles", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.text "description"
t.boolean "status", default: true
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.string "email"
t.string "name"
......
......@@ -2,10 +2,13 @@
namespace :admin do
task create_acc: :environment do
Admin.create do |ad|
ad.email = 'admin@mi.com'
ad.password = '11111111'
ad.password_confirmation = '11111111'
3.times do |i|
Admin.create do |ad|
ad.email = "admin#{i}@mi.com"
ad.password = '11111111'
ad.password_confirmation = '11111111'
ad.rule_id = i
end
end
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment