最近要开始一个新的项目,用ror来实现,把框架搭建好,Let's coding!
我的项目命名规则是,后台管理的的控制器统一用负数形式,前台则是单数,这样的代码看起来比较规范,无二义性。
全局过滤器判断是否需要登陆need_login? 放在application_controller.rb中
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :need_login?
private
def need_login?
controller_name = params[:controller]
if controller_name.pluralize ==controller_name
if session[:adminer].blank?
flash[:notice] = "请先登录"
redirect_to "/admins"
end
else
if session[:officex].blank?
flash[:notice] = "请先登录"
redirect_to "/"
end
end
end
end
登陆和退出action放在admins_controller下
def login
sys_user = SysUser.find_by_name_and_password(:name => params[:name], :password => SysUser.encrypted_pwd(params[:password))
if sys_user.blank?
flash[:notice] = "账号或密码错误"
redirect_to "/admins"
else
session[:adminer] = sys_user
redirect_to "/admins/admin"
end
end
def logout
reset_session
redirect_to "/admins"
end
下午新建了一个Sys_menus的数据表,用来后台菜单的显示,以前是写死的,现在用数据库的方式,就可以自己维护了
sys_menus的字段有action_name,action_url,parent_id,sort
使用方法:在admins_helper.rb中添加两个方法get_permission 和 is_visual
#返回当前用户的权限值
def get_permissions
sys_user = SysUser.find session[:adminer][:id]
sys_use_permission = []
sys_user.sys_roles.each do |r|
role_permission = []
r.sys_action_permissions.each do |p|
role_permission << p.permission_value
end
sys_user_permission = sys_user_permission + role_permission
end
sys_user_permission
end
#判断是否显示,如果是superuser则跳过
def is_visual value
session[:adminer][:name]=="superuser" or get_permissions.uniq.include?(value)
end
admins_controller.rb
def nav
@parents = SysMenu.where("parent_id=0").order("sort DESC").all
@actions = SysMenu.where("parent_id!=0").order("sort DESC").all
render :layout => false
end
nav.rhtml
<% @parents.each do |p| %>
<label><%= p.action_name%></label>
<ul>
<% @actions.each do |a| %>
<% next if a.parent_id != p.id %>
<% if is_visual(a.action_url)%><li><a href="<%=a.action_url%>"><%=a.action_name%></a></li>
<%end%>
<%end%>
</ul>
怎么样才能让权限控制更加flexible呢?
在sys_roles_controller.rb中加入refresh_permission
#只有superuser才可以调用
def refresh_permission
if session[:adminer].name != "superuser"
render :text => "Sorry! You are not allowed."
return
end
SysActionPermission.create_all_permissions
end
重点就在这里拉,create_all_permissions的实现
def self.create_all_permissions
require "find"
root = SysActionPermission.find_by_parent_id(0)
root = SysActionPermission.create({:permission_name=>"根节点",:permissionvalue=>"/",:parent_id=>0,:sort=>100}) if root.blank?
dir = File.expand_path(Rails.root) + "/app/controllers"
actions = []
Find.find("#{dir}/") do |path|
Find.prune if path =~ /.svn/ #过滤一些目录下不需要的文件
if File.file?(path) and path.end_with?("_controller.rb") and path.end_with?("admins_controller.rb")
parent_name = path.sub(dir,'').sub('_controller.rb','')
if parent_name == parent_name.pluralize
parent = SysActionPermission.find_by_permission_value_and_parent_id(parent_name, root.id)
obj = eval(ActiveSupport::Inflector.camelize(path.sub(dir, '').sub('.rb',''))).new
#若二级权限已存在则不创建
parent = SysActionPermission.create(:permission_name => "#{parent_name}", :permission_value => "#{parent_name}", :parent_id => root.id) if parent.blank?
parent_id = parent.id
all_public_methods = obj.public_methods(false)
for action_name in all_public_methods
#若已存在则不创建
value = "#{parent_name}/#{action_name}"
if(SysActionPermission.find_by_permission_value_and_parent_id(value, parent_id).blank?)
actions << {:permission_name => "#{value}", :permission_value => "#{value}", :parent_id => parent_id}
end
end
end
end
end
SysActionPermission.create(actions.uniq)
all_has_created_permissions = SysActionPermission.all
for permissrions in all_has_created_permissions.compact
next if permissrions.parent_id == 0
#查看控制器存在与否
if permissrions.permission_value.count("/") == 1
if !File.exist?(File.expand_path(Rails.root) + "/app/controllers" + permissrions.permission_value + "_controller.rb")
ActiveRecord::Base.connection.execute("DELETE FROM sys_action_permissions WHERE parent_id = #{permissrions.id} or id = #{permissrions.id}")
end
elsif permissrions.permission_value.count("/") == 2
controller = permissrions.permission_value.split("/")[1] + "_controller"
action = permissrions.permission_value.split("/")[2]
begin
public_methods = eval(ActiveSupport::Inflector.camelize(controller)).new.public_methods(false)
if !public_methods.include?(action.to_sym)
permissrions.destroy
end
rescue => e
p e
end
end
end
end