Tempos atrás estava procurando algo que facilitasse minha vida com autenticação e controle de acesso em RoR. Passei algum tempo quebrando um galho com a engine do
Goldberg. Boa, mas muito gigante para aplicações simples.
Cheguei nesse tutorial rápido e espero que ajude, não inventei nada, só reescrevi a roda:
1. Crie uma nova aplicação "rails novosite"
2. "cd novosite"
3. Instale o plugin "gem install login_generator" e em seguida gere os arquivos de autenticação com "ruby script/generate login LoginSystem" onde LoginSystem será o nome do seu controller de autenticação.
4. Crie um migrate para criar a estrutura do controle de acesso "ruby script/generate migration create_acl_schema".
5. Coloque o conteudo abaixo no migrate criado
class CreateAclSchema < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :login, :string, :limit=>40, :null=>false
t.column :name, :string, :limit=>40
t.column :password, :string, :limit=>40, :null=>false
t.column :updated_at, :datetime
t.column :created_at, :datetime
t.column :access, :datetime
t.column :nick, :string
end
create_table :roles do |t|
t.column :name, :string, :limit=>40, :null=>false
t.column :info, :string, :limit=>80
end
create_table :permissions do |t|
t.column :name, :string, :limit=>40, :null=>false
t.column :info, :string, :limit=>80
end
create_table :roles_users do |t|
t.column :user_id, :integer, :null=>false
t.column :role_id, :integer, :null=>false
end
create_table :permissions_roles do |t|
t.column :role_id, :integer, :null=>false
t.column :permission_id, :integer, :null=>false
end
end
def self.down
drop_table :users
drop_table :roles
drop_table :permissions
drop_table :roles_users
drop_table :permissions_roles
end
end
6. Crie outro migrate para a entidade que iremos testar "ruby script/generate migration carro"
7. Coloque o conteudo abaixo no migrate criado
class CreateCarros < ActiveRecord::Migration
def self.up
create_table :carros do |t|
t.column :user_id, :integer
t.column :name, :string
t.column :age, :integer
t.column :updated_at, :datetime
t.column :created_at, :datetime
end
end
def self.down
drop_table :carros
end
end
8. Configure o config\database.yml e crie a base recomendada
9. execute "rake migrate" para criar tabelas na base de dados e depois "ruby script\generate scaffold Carro" para criar um CRUD de teste para a entidade Carro.
10. Crie os seguintes arquivos:
app/models/permission.rb
class Permission < ActiveRecord::Base
has_and_belongs_to_many :roles
end
app/models/role.rb
class Role < ActiveRecord::Base
has_and_belongs_to_many :permissions
has_and_belongs_to_many :users
end
lib/acl_system.rb
module ACLSystem
include LoginSystem
protected
def authorize?(user)
required_perm = "%s/%s" % [ params['controller'], params['action'] ]
if user.authorized? required_perm
return true
end
return false
end
end
11. Em app/models/user.rb modifique adicionando os seguintes métos e relacionamento:
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
# Return true/false if User is authorized for resource.
def authorized?(resource)
match=false
permission_strings.each do |p|
r = Regexp.new(p)
match = match || ((r =~ resource) != nil)
end
return match
end
# Load permission strings
def permission_strings
a = []
self.roles.each{|r| r.permissions.each{|p| a<< p.name }}
a
end
E em app/controllers/application.rb para:
require_dependency "acl_system"
class ApplicationController < ActionController::Base
include ACLSystem
model :user
E em app/controllers/carros_controllers.rb para:
class CarrosController < ActiveRecord::Base
before_filter :login_required
Obs: "before_filter :login_required" exige que o usuário esteja logado e tenha permissao de acesso.
12. Inicie o servidor e acesse "localhost:3000/login_system/signup" crie dois usuários de teste
13. Utilize o script para criar as permissões, regras e associar ao usuário:
INSERT INTO roles (id, name, info) VALUES (1, 'admin', 'Admistrador');
INSERT INTO roles (id, name, info) VALUES (2, 'normal', 'Usuario Comum');
INSERT INTO roles_users (user_id, role_id) VALUES (1, 1);
INSERT INTO roles_users (user_id, role_id) VALUES (2, 2);
INSERT INTO permissions(name,info) VALUES('.*/.*', 'Acesso Total');
INSERT INTO permissions(name,info) VALUES('carros/index', 'Acesso reduzido');
INSERT INTO permissions(name,info) VALUES('carros/list', 'Acesso reduzido');
INSERT INTO permissions_roles (permission_id, role_id) VALUES (1, 1);
INSERT INTO permissions_roles (permission_id, role_id) VALUES (2, 2);
INSERT INTO permissions_roles (permission_id, role_id) VALUES (3, 2);
14. Pronto... agora é só testar Acesse "http://localhost:3000/carros/" com o segundo usuário criado e verifique que existe acesso. Mas não é possível criar um novo carro. Para o primeiro usuário criado o acesso é total.
Referências:
LoginGeneratorACLSystem
LoginGenerator
Um comentário:
Vale a pena lembra que em tabelas associativas ( habtm ) não é necessário, e até mesmo aconselhável a não utilizar o id. Portanto utilize ao criar as tabelas:
create_table :roles_users, :id => false do |t|
create_table :permissions_roles, :id => false do |t|
Postar um comentário