티스토리 뷰
안녕하세요 여러분~!
이번 시간에는 User별 권한 설정에 대해서 알아보겠습니다.
1. User별 권한 설정이 왜 필요할까?
한번 생각해봅시다. 어떤 서비스에 글을 게시할 수 있는 게시판 기능이 있습니다. 게시판을 이용하는 유저 A가 글을 게시합니다. 그리고 잠시 후에 유저 B가 게시판에 들어와 유저 A의 글을 읽습니다. 별로 마음에 들지 않습니다. 그래서 유저 B는 유저 A의 글을 마음대로 삭제해버립니다.... 이런 상황, 괜찮은 걸까요?
만약, 모든 유저가 모든 글에 대해 수정, 삭제가 가능하다면 이처럼 말도 안되는 상황이 생겨버릴 것입니다.
따라서! 우리는 유저가 누구인지에 따라 권한을 설정해주는 방법에 대해서 배워보겠습니다.
2. Gem을 이용하자.
우리는 Gem에서 제공하는 기능을 이용해 권한을 설정할 수 있습니다. 바로 Pundit Gem인데요, 본격적으로 젬을 설치하기에 앞서 c9 작업시 CRUD+LOGIN이 구현된 상태의 Workspace가 없으시다면 다음 주소의 깃을 clone해서 만들어 주셔도 됩니다!
https://github.com/likegayeon/crudloginset.git
* 깃 클론시, 꼭 bash 창에 bundle install 및 rake db:migrate 잊지 마세요 *
그럼 이제 젬을 설치해보겠습니다.
- 먼저, Gemfile에 젬에 대한 정보를 가져오기 위해 다음과 같이 써줍니다.
- 그 다음에는 application_controller에 include Pundit을 써주시는데 설치 전에 꼭 필요한 과정이니 깜빡하지 말아주세요!
- 그리고 bash창에 본격적으로 설치를 위해서 bundle install 해주시고 rails g pundit:install을 하시면 app 폴더 안에 policies 폴더가 생깁니다. 마지막으로 rails g pundit:policy post를 하시면 policies 안에 post_policy.rb 파일이 생깁니다.
이 post_policy.rb 파일이 바로 유저의 게시글(post)에 대한 권한을 설정해 줄 파일입니다!
3. 권한을 설정해보자.
권한을 설정해주기 위해서는 특정한 메소드가 필요합니다.
다음과 같이 gem 설치 후 생성된 post_policy.rb 파일에 두 가지의 메소드를 정의해줍니다.
- initialize : user와 post를 @비둘기로 처리
- update? : user와 post에 대한 권한이 있는지 검사 -> admin?이라는 권한 확인 메소드 호출
**update? 메소드는 정의 그대로 user.admin?(@post) post에 대해 user가 권한이 있는가(admin?) 라는 검사를 유저가 받게 하는 메소드입니다. 즉, 직접적으로 어떠한 조건에 따라 권한 확인하는 메소드는 update?안의 admin?메소드입니다.
그렇다면 admin?메소드도 정의해줘야겠죠? user.rb 파일에 다음과 같이 정의해줍니다.
작성한 admin? 메소드의 정의를 한번 살펴보겠습니다.
' self == post.user '
이 부분은 권한이 있는지 확인하는 하나의 조건이라 할 수 있는데요!
여기서 self란, admin? 메소드를 호출해 권한 검사를 받는 현재 유저 자신을 말합니다.
또한 post.user란 말 그대로 post의 user, 즉 post를 작성한 사람을 말합니다. 이 두 user가 일치한다면 admin?에 대한 응답은 true일 것이고(권한 有) 그렇지 않다면 false가 될 것입니다.(권한 無)
.
.
.
이렇게 권한을 설정해주기 위하여 총 세 가지의 메소드 1.initialize 2.update? 3.admin?에 대해서 정의해주었습니다.
메소드를 호출하기 위해서는 당연히 정의에서 끝나면 안되겠죠? 이 메소드들을 가져오기 위해서 우리는 권한이 필요한 부분에 적.절.히. 입력해주어야 합니다.
그 전에 잠깐!
아까도 말했다 시피, 실질적으로 검사를 확인하는 것은 admin? 메소드이며, admin? 메소드는 update? 메소드를 거쳐서 사용된다고 했었죠!
다시 한번 정리하자면,
user의 post에 대한 권한을 조건(self == post.user 현재 user가 글을 작성한 본인이 맞는가?)으로 실제로 검사하는 메소드는 admin?입니다. 그리고 이 admin? 메소드를 가져오기 위해서는 admin?메소드를 user가 post에 대한 것임을 확인하는 update? 메소드에서 불러와야합니다.
그리고, 아래와 같이 update?메소드는 권한이 필요한 곳에 적절히 입력해서 호출이 되도록 해줘야 하죠!
권한이 필요한 곳은 어디일까요? 지금 우리는 수정, 삭제에 대한 유저의 권한을 다루고 있으므로 수정, 삭제를 정의한 곳이 되겠습니다.
수정(edit)액션과 삭제(destroy)액션이 정의된 home_controller에 다음과 같이 써줍니다.
- authorize : pundit gem에서 제공하는 기능 중 하나로 수정할 post 혹은 삭제할 post에 대한 권한 검사를 도와줍니다.
4. 결과를 확인해보자.
지금까지의 코드 작성이 완료되었다면!
1) 프로젝트를 run해주시고 sign up 후, login이 된 상태에서 두 개의 글을 작성해주세요.
2) 그리고 나서 둘 중 하나의 글을 수정 혹은 삭제해줍니다. 두 액션이 모두 성공된 것을 볼 수 있습니다!
3) 이번에는 우리가 설정해준 권한에 따라 권한이 없음을 나타낸 결과를 확인하기 위해서! 다른 유저로 sign up 후, login해주세요.
4) 다른 유저로 로그인이 된 상태에서 아까 처음에 썼던 글을 수정 혹은 삭제해보세요.
다음과 같은 에러가 뜬다면 성공입니다^^
이거슨 좋은 에러~ 참 에러~
(번외) 이렇게도 활용할 수 있어요!
지금까지 pundit 젬으로 게시글에 대한 수정, 삭제 권한을 설정해보았습니다. 그렇다면 게시물 공개에 대한 권한은 설정할 수 없을까요?
(페이스북의 게시글 공개 범위 설정)
- Step 1 : Post(게시물) 모델에 공개 설정을 반영해줍니다.
어떻게? Post 모델에 공개 권한에 대한 칼럼을 추가해주면 되겠죠!
공개 범위를 뜻하는 range 등 임의의 이름으로 칼럼의 이름을 정하고, 데이터형은 integer로 저장해줍니다.
(ex. 1=비공개, 2=친구공개, 3=전체공개)
*post의 title, content와 같이 string, text 등으로 하지 않은 이유는?
비공개, 친구공개 등 공개 범위에 대한 이름을 일일이 정해주는 것보다 integer의 형태로 숫자로 특징을 짓는 것이 편리하기 때문입니다.
- Step 2 : 공개 권한을 검사하는 메소드를 정의해줍니다.
아까 구현한 admin? 메소드 처럼 유저에게 게시물 공개 권한, 즉 게시물이 공개 가능한, 다시 말해 읽기 권한이 있는지 검사하는 메소드가 필요하겠죠!
그렇다면 읽기 권한이 있는 경우는 언제일까요? 생각해봅시다!
1) 비공개 글인 경우 : 본인(self)이 작성자일 때
2) 친구공개 글인 경우 : 본인(self)과 작성자가 친구 사이 & 게시물(post)이 비공개가 아닐 때
3) 전체공개 글인 경우 : 본인(self)과 작성자가 친구 사이가 아닐 때 & 게시물(post)이 전체공개
이 세 가지 경우를 조건으로 read_admin? 메소드 안에 다 정의하기 위해서는 if문으로 나누어 주면 되겠죠!
**친구 사이는 어떻게 표현하나요?
has_friendship 이라는 gem을 이용하면 가능합니다. Gem 문서를 참고해주세요!
https://github.com/sungwoncho/has_friendship
- Step 3 : 게시물 공개 범위를 설정했으면 게시글의 범위를 입력할 수 있게 합시다.
radio button으로 범위를 선택할 수 있도록 합니다.
칼럼 이름에는 아까 정해준 range, 값에는 1=비공개, 2=친구 공개, 3=전체 공개 중 각각 해당되는 숫자를 입력해 줍니다.
- Step 4 : 읽기 권한에 따라 공개 범위를 나타내어 줍니다. (출력 부분)
게시물 공개 권한, 즉 유저에 입장에서 읽기 권한의 유무에 따라 글의 공개 범위를 나타내어 주어야 합니다. view 파일에서 게시물(post)을 출력하는 부분을 read_admin? 메소드가 호출되도록 if문으로 감싸줍니다.
따라서, 사용자가 읽기 권한이 있다면(read_admin? true) 게시글(post)은 출력이 될 것이고 권한이 없다면(read_admin? false) 출력이 되지 않아 유저 입장에서 게시물을 읽을 수 없게 됩니다.
.
.
.
지금까지 유저별 권한 설정을 도와주는 pundit gem과 SNS에서 활용 가능한 친구 사이에 따른 게시글 공개 설정의 경우 has_friendship gem을 같이 활용하면 가능한 것임을 알 수 있었습니다. 서비스에는 유저가 있고 유저별로 다른 권한을 갖는 것은 기본 기능이므로 꼭 알아두시고 나중에 잘 활용하셨으면 좋겠습니다~^^
참고 문서
https://github.com/elabs/pundit
'교육팀과 함께하는 > ruby on rails' 카테고리의 다른 글
[방학 2주차] REST API 정복하기 - (1) RESTful & (2) 다음 카카오 검색 API & (3) 네이버 성인검색어 판별 API (3) | 2017.08.14 |
---|---|
[방학 7주차] AWS 배포하기 (1) | 2017.08.13 |
[방학 6주차] 좋아요 & 검색 기능 (4) | 2017.08.13 |
[방학 2주차] 소셜로그인 (0) | 2017.08.03 |
[방학 1주차] 스캐폴딩과 리소스 라우팅 (0) | 2017.07.09 |