Allow와 Deny

Sidebar 8.5

번역 완료율

이 장에서는:

  • Allow와 Deny 콜백에 대하여 배운다.
  • 콜백이 호출되는 순서를 이해한다.
  • 미티어의 보안시스템 덕분에, 우리는 변경하고자 할 때마다 메서드를 정의하지 않고도 데이터베이스 수정을 제어할 수 있다.

    왜냐하면 post를 등록할 때 ‘post’ 메서드를 사용하는 경우, post에 속성을 추가하거나 URL이 이미 등록되어 있을 때 특정한 작업을 해야 하는 것 같은 보조적인 과제를 해야 했기 때문이다.

    한 편, post를 변경하거나 삭제할 때에는 새로운 메서드를 만들 필요는 없었다. 단지 사용자가 이런 작업을 할 수 있는 권한을 가지고 있는지를 검사하기만 하면 되었다. 그리고 이 작업은 allowdeny 콜백을 사용하여 쉽게 할 수 있었다.

    이들 콜백을 사용함으로써 데이터베이스 수정을 선언적으로 처리할 수 있고, 어떤 수정작업을 할 지를 지정할 수 있다. 그리고 이들이 계정 시스템과 통합되어 있다는 사실은 추가 보너스이다.

    다중 콜백

    우리는 필요한 만큼 allow 콜백을 정의할 수 있다. 단지 변경이 발생했을 때 그 콜백들 중에서 최소한 하나만 true를 리턴하면 된다. 그러므로 브라우저에서 Posts.insert가 호출될 때(애플리케이션의 클라이언트 코드이든, 브라우저 콘솔이든 상관없이), 서버는 순서대로 호출하여 그 중 하나가 true를 리턴할 때까지 insert 검사를 한다. 만약 하나도 발견하지 못하면 insert는 허용되지 않고, 클라이언트에 403 오류를 리턴한다.

    유사한 방식으로 하나 이상의 deny 콜백을 정의할 수 있다. 만약 이들 가운데 어느 것이라도 true를 리턴하면, 변경은 취소되고 403이 리턴된다. 이 로직은 성공적인 insert를 위해서는 하나 또는 그 이상의 allow와 모든 deny 콜백이 실행된다는 것을 의미한다.

    주: n/e는 실행되지 않음을 의미한다.
    주: n/e는 실행되지 않음을 의미한다.

    다시말하면, 미티어는 콜백 목록을 따라서 실행하면서 처음엔 deny로 시작하여 다음엔 allow, 그리고 모든 콜백을 그 중 하나가 true를 리턴할 때까지 실행한다.

    이 패턴의 실제 예제는 두 개의 allow() 콜백 - 하나는 post가 현재 사용자의 소유인지를 검사하고, 두 번째는 현재 사용자가 관리자 권한을 가지고 있는지를 검사하는 - 을 가질 수 있다. 만약 현재 사용자가 관리자이면 이는, 그 두 콜백 중의 하나는 적어도 true를 리턴하므로, 어떤 post도 수정할 수 있다는 것을 의미한다.

    대기시간 보정

    데이터베이스를 변경시키는 메서드들(.update()와 같은)은 다른 메서드와 마찬가지로 대기시간 보정이 적용된다는 사실을 기억하라. 그래서 만약 브라우저 콘솔에서 독자가 작성하지 않은 post를 삭제하려고 시도하면, post가 로컬 컬렉션의 처리에 따라서 일단 삭제되었다가 서버로부터의 정보 - 사실은 삭제가 되지 않았다는 - 가 오면 다시 나타나는 모습을 볼 수 있을 것이다.

    물론 이런 행태가 콘솔에서 구동될 때는 문제가 되지 않는다(결국 사용자가 콘솔에서 시도하여 엉망이 되어도, 자기 브라우저에서 일어나는 것이니까 문제는 아닌거다). 하지만, 이것이 사용자 인터페이스에서는 일어나지 않도록 확실하게 해 둘 필요는 있다. 이를테면, 삭제할 수 없는 도큐먼트에 대하여는 삭제 버튼이 보여지지 않도록 할 필요는 있는 것이다.

    고맙게도, 접근권한에 대한 코드가 클라이언트와 서버에서 공유(이를테면, 라이브러리 함수 canDeletePost(user, post)를 작성하여 공유되는 /lib 디렉토리에 둘 수 있다)될 수 있기 때문에, 이렇게 코딩하는 것이 보통 과도하게 많은 코드를 요구하는 것은 아니다.

    서버에서의 접근 권한

    접근제어 시스템이 클라이언트로부터 시도되는 데이터베이스 변경시도에 한하여 적용되는 것을 기억하라. 서버에서 미티어는 모든 연산이 허용된다.

    클라이언트에서 호출될 수 있는 deletePost 미티어 메서드를 서버 쪽에 작성한다면, 누구나 어떤 post든지 삭제할 수 있게 된다. 그러므로 그 메서드 내부에서 사용자의 접근 권한을 검사하지 않으면 안될 것이다.

    Deny 함수를 콜백으로 사용하기

    마지막으로, deny로 할 수 있는 한 가지 묘기는 이것을 “onX” 콜백으로 사용하는 것이다. 이를테면, 다음과 같은 코드를 사용하면 최종 수정 시간을 얻을 수 있다:

    Posts.deny({
      update: function(userId, doc, fields, modifier) {
        doc.lastModified = +(new Date());
        return false;
      },
      transform: null
    });
    

    deny 콜백이 모든 성공적인 update에서 실행되므로, 이 콜백이 실행되면서 구조화된 방식으로 도큐먼트를 변경한다는 것을 알 수 있다.

    명백히, 이 기술은 일종의 핵이므로 대신 메서드를 사용하여 update를 수행하기를 원할 수 있다. 그럼에도 불구하고, 이것을 알아 둘 만하며, 언젠가는 일종의 beforeUpdate 콜백 같은 것이 이용되기를 바란다.