티스토리 뷰

해당 글은 https://blog.naver.com/kbs4674/221069915874 로 부터 게시글이 이전되었습니다.

 

게시판이 운영되는 거의 모든 사이트는 최소 '관리자'와 '유저' 이 2가지로 계급이 나뉘어 있을겁니다.

유저는 글을 쓰거나, 자신의 글에 대해서만 수정/삭제가 가능한 반면, 관리자는 게시글을 누구의 글이든 삭제 혹은 수정을 할 수 있겠죠.

 

이렇게 홈페이지 운영에 있어서 효율적인 관리를 위해선 '권한'이라는 계급이 필요합니다.

이번 시간에는 Devise rolify, cancancan Gem을 이용해서 '권한설정' 에 대해 알아보겠습니다.


 시작 전 유의사항 

 1. Gem : devise이 기본적으로 깔려있어야 합니다.

 참고  devise Gem 설치법 [클릭]

 2. 필자는 CRUD 사용 시, scaffold를 사용했습니다.


 

  • Rolify + Cancancan 밑준비

1.  Gemfile  열람 후, 다음 내용을 입력합니다.

gem 'cancancan'
gem 'rolify'

그리고 Gem을 설치합니다.

bundle install

 

2. Gem 설치가 끝난 후, 명령어 터미널에 다음 명령어들을 입력해주세요.

rails generate cancan:ability
rails generate rolify Role User

위 명령어를 다 입력하면

  • 2개의 Model 파일이 생성됩니다.
  • 1개의 테이블이 생성됩니다.
  •  app/models/user.rb  에는 rolify라는 글자가 추가되어 있는것도 볼 수 있습니다 :D

 참고  Migrate 버전 명시가 없는 경우

## db/migrate/[버전]_rolify_create_roles.rb

class RolifyCreateRoles < ActiveRecord::Migration

간혹 일부 Rails 버전에서는  db/migrate/[버전]_rolify_create_roles.rb  에서 Migrate 버전이 명시되지 않는 경우가 있습니다.

이런 경우에는 직접 Migrate 파일을 열람 후, 다음과 같이 수정해주세요.

## db/migrate/[버전]_rolify_create_roles.rb

class RolifyCreateRoles < ActiveRecord::Migration
=> class RolifyCreateRoles < ActiveRecord::Migration[5.2]

저는 5.2 버전이라서 위와같이 명시했습니다.

 

3. 위 작업이 다 완료 되셨으면 schema 업데이트를 해준 후, 서버를 껏다 켜주세요.

rake db:migrate

 

 

  • 권한 명칭 설정 및 회원가입 시 기본 권한 부여

지금으로서는 회원가입을 하게되면 유저들은 기본 권한(Default 권한)도 없이 생성되게 됩니다.

저희는 유저들에게 회원 가입 시 자동적으로 기본 권한을 주게 하고자 합니다.

 

1. 회원가입 시 기본 권한을 주려면  app/models/user.rb  파일에 다음과 같이 내용을 추가하면 됩니다.

class User < ApplicationRecord
  after_create :assign_default_role
  ...
 
  def assign_default_role
    add_role(:student)
  end
 
  ...
 
end

위 설정은 누구나 회원가입 시 기본적으로 'student'라는 이름의 권한을 부여합니다.

 

 

  • Rolify + Cancancan 권한 설정

어떤 게시판에 있어, 만약 게시글 주인인 경우 남들이 자기글을 수정/삭제를 할 수 없게 하면서 권한자가 운영자(admin)인 경우, 모든 게시글을 지울 수 있게 설정을 해보겠습니다.

 

1. 게시판 Controller로 이동하시고, 코드에 다음 내용을 추가합니다.

## app/controllers/posts_controller.rb

class PostsController < ApplicationController
  # 이제 Post의 모든 액선에 권한이 적용
  load_and_authorize_resource
  
  def index
    ...
  end
  
  ...
end

 참고  만일 전체가 아닌 특정 액션에 대해서만 적용을 하고싶다면, 위 코드는 쓰지말고, 아래 코드를 써 보세요.

def show
  @article = Article.find(params[:id])
  authorize! :read, @article
end

 

2. 권한을 설정할 model파일로 가서 파일 내에  resourcify  문자를 추가해줍니다.

class Post < ApplicationRecord
    resourcify
    ...
end

 

3.  app/models/ability.rb  파일로 이동합니다.

여기는 Admin, 일반 유저 등 직급에 따라 권한을 설정하는 곳입니다.

# frozen_string_literal: true

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
	#어드민 (admin 이라는 권한이 있는 경우)
	if user.has_any_role? :admin
		can :manage, :all
	
	# 일반 유저(로그인을 안한 비회원 등)
	else
		can :read, :all
	end
  end
end

일단 작은 밑그림을 그려서 표현해보면 위 코드와 같습니다.

위 코드는 기본적으로 Admin이 모든 권한을 가진 상태입니다.

 참고 

1) initialize에 따라오는 user 변수는 Devise의 current_user에 대한 정보가 담겨져 있습니다.

2) has_any_role? 은 current_user의 권한을 체크합니다.

 

관리명칭은 Controller 내 액션 이름에 따라 결정되니 참고바랍니다. 명칭과 그에 해당하는 역할은 아래에 정리해봤습니다.

## 관리 명칭 설명

 # 공통
 :manage - 모든 액션 접속 허용
 :read - 게시판 글 목록 및 글 열람
 
 # Scaffold Controller 액션 내 역할
 :show - 게시글 열람
 :new - 게시글 작성
 :create - Controller 내 DB 생성
 :edit - 게시글 편집
 :update - Controller 내 DB 수정
 :destroy - Controller 내 게시글 삭제

 

저는 위 액션의 특징을 이용해서

  • Admin : 모든 액션 접근 허용

  • 로그인 된 일반유저(student) : Post 모델 속에서 글 열람 및 자신이 작성한 게시글 편집/삭제만 가능

  • 로그인 된 일반유저(student) : Manage 모델 속 index 페이지 접근 불가
  • 비로그인 유저 : Post 모델 속 글 열람만 가능

위 규칙을 아래와 같이 코드로 적용해봤습니다.

# frozen_string_literal: true

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
	if user.has_any_role? :admin
		can :manage, :all
		can :read, :all
	elsif user.has_any_role? :student
		can :read, :all
		can [:index, :show, :new, :create], Post
		can [:edit, :update, :destroy], Post, user_id: user.id
		cannot [:index], Manage
	else
		can :read, :all
	end
  end
end

코드 변경 후, 서버를 껏다 켜서 한번 확인을 해보세요!

 

만약에 student 권한을 가진 2번 유저가

1번 유저가 작성한 게시글 삭제를 시도하면

 

위와같이 권한 에러를 일으킵니다.

반면에 admin 권한을 가진 1번 유저가 2번 유저가 작성한 게시글 삭제를 시도하면 삭제가 아주 잘 됩니다.

 

4. 하지만 아직 한 가지 불편한 점이 남았습니다.

Edit, Destroy 버튼에 대해서는 내가 작성한 글에서만 보여야 하지만, 현재 모든 사람들에게 보여지는 상황입니다.

(그래도 Admin을 제외하고 남이 쓴 글을 수정/삭제 시도 시 권한 에러가 뜨지만요..)

 

이를 해결하기 위한 방법은

View 파일에 다음과 같이 코드를 써내면 됩니다.

## app/views/posts/index.html.erb

<% @posts.each do |post| %>
    ...
	<% if can? :update, post %>
       	<td><%= link_to 'Edit', edit_post_path(post) %></td>
	<% end %>
	<% if can? :destroy, post %>
       	<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
	<% end %>
    ...
<% end %>
## app/views/posts/show.html.erb

<% if can? :update, @post %>
	<%= link_to '수정', edit_post_path(@post) %>
<% end %>

<% if can? :destroy, @post %>
	<%= link_to '삭제', @post, method: :delete, data: { confirm: '정말로 삭제하시겠습니까?' } %>
<% end %>

어드민 계정(kbs4674@g.g)과 일반 계정(test4674@naver.com)

그럼 위와같이 권한에 따라 보여지는 버튼이 달라지는 것을 확인할 수 있습니다.

 

 

  • 간단한 메소드 소개

1) 여러 개의 권한 중 조건에 맞는 권한 탐색

## teacher 유저는 admin 권한을 가지고 있다.
## kid 유저는 student 권한을 가지고 있다.

if teacher.has_any_role? :admin, :student
# => true

if kid.has_any_role? :admin, :student
# => true

 

2) 하나의 권한 탐색

## teacher 유저는 admin 권한을 가지고 있다.
## kid 유저는 student 권한을 가지고 있다.

if teacher.has_role? :admin
# => true

if kid.has_role? :admin
# => false

 

3) 권한 부여

teacher = User.find(1)
teacher.add_role(:admin)
# => true

 

 

  • Rolify + Cancancan 권한 부여

일단 관리자 권한을 부여하는방법은 크게 3가지가 있습니다. :

  •  rails c  콘솔 명령어로 주는 방법

  •  db/seed.rb  파일에 미리 등록시키기 및 링크를 통해 주는 방법

  • 관리자 메뉴를 통한 권한 부여 (추가적인 Gem 설치 필요) [참고 : 클릭]

1. 콘솔 명령어 사용

1) 터미널에 Console 명령어 입력합니다.

rails c

 

2) 터미널에 다음 명령어를 입력해주면 계정 생성 및 권한이 적용이 됩니다.

user = User.create( email: 'kbs4674@naver.com', password: '123456' )
user = User.find(1)
user.add_role :admin

 

2.  db/seed.rb  파일에 미리 등록시키기

1)  db/seed.rb  파일에 다음 내용을 등록해주세요.

user = User.create( email: 'kbs4674@naver.com', password: '123456' )
user = User.find(1)
user.add_role :admin

 

2) 터미널에 다음 명령어를 입력해주면 계정 생성 및 권한이 적용이 됩니다.

rake db:seed

 

 

  • Heroku : 콘솔 활성화 시키는 법

1. Heroku 홈페이지

1) 관리페이지 우측에 보면 More이 보일겁니다.

More 클릭 후 Run console 클릭

 More -> 'Run Console'

2) Console 창에 rails c 입력을 해주세요.

rails c를 입력하고, 'Run'을 클릭하면..

3) Console이 활성화 되었습니다.

 

2. c9 내 커멘드창을 통해 heroku 서버 내 rails console 접근

1) 터미널 창을 통해  heroku login 서버 연동 및 로그인을 합니다.

git remote add heroku [Heroku Git 주소]
heroku login -i

 

2) 헤로쿠 서버 내 콘솔을 활성화 시킵니다.

heroku run rails c

 

3) 터미널을 통해 헤로쿠 콘솔이 활성화 되었습니다.

 

 

  • 자료 참고

1. devise + rolify + cancancan Tutorial [클릭]

2. Github - Cancancan [클릭]

3. rolify + cancancan 설치 및 설정해보기 [클릭]

 

루비온 레일즈 Ruby on Rails ROR

댓글
댓글쓰기 폼
공지사항
Total
148,739
Today
105
Yesterday
430
링크
«   2021/10   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
글 보관함