가이드

보안

인증, 인가, 유효성 검사에 대해 알아봅니다.

인증

Orion은 현재 인증 기능을 별도로 제공하지 않으며, 앱에 필요한 인증 기능은 개발자가 직접 구성해야 합니다. 이를 위해 Laravel Passport 또는 Laravel Sanctum 사용을 권장합니다.

인가

모델 컨트롤러와 연관관계 컨트롤러는 모두 모델 정책을 이용해 현재 인증된 사용자가 특정 작업을 수행할 수 있는지 여부를 판단합니다.

권장하지는 않지만, 상황에 따라 특정 컨트롤러에서 인가 검사를 비활성화해야 할 수도 있습니다. 이 경우 Orion\Concerns\DisableAuthorization 트레이트를 사용하세요.

<?php

namespace App\Http\Controllers\Api;

use App\Models\Post;
use Orion\Concerns\DisableAuthorization;

class PostsController extends ApiController
{
    use DisableAuthorization;

    /**
     * @var string $model
     */
    protected $model = Post::class;
}

Sanctum(또는 기타 커스텀 Auth 가드)과 함께 사용하기

기본적으로 인가 시 현재 인증된 사용자를 확인하는 데 api 가드가 사용됩니다.

하지만 config/orion.phpauth.guard 값을 설정하거나 컨트롤러의 resolveUser 메서드를 오버라이드하여 사용자를 확인하는 방식을 변경할 수 있습니다.

<?php

namespace App\Http\Controllers\Api;

use App\Models\Post;

class PostsController extends ApiController
{
    /**
     * @var string $model
     */
    protected $model = Post::class;

     /**
     * 가드를 기반으로 현재 인증된 사용자를 조회합니다.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function resolveUser()
    {
        return Auth::guard('sanctum')->user();
    }
}

부모 엔티티 인가

연관관계 작업은 정책에 부모 엔티티라는 추가 인자를 전달합니다. 이 인자를 활용하면 사용자가 특정 부모 엔티티의 컨텍스트 안에서 연관관계 엔티티에 대해 특정 작업을 수행할 수 있는지 추가로 검사할 수 있습니다.

class PostPolicy
{
    public function update($user, $post)
    {
        return $post->user_id === $user->id;
    }
}

class PostMetaPolicy
{
    public function update($user, $postMeta, $post) // <---- 여기서 $post는 부모 엔티티입니다
    {
        // 검사는 관계 엔티티 $postMeta가 아니라
        // 부모 엔티티 $post에 대해 수행된다는 점에 유의하세요
        return Gate::forUser($user)->inspect('update', $post); 
    }
    
    public function create($user, $post)
    {
        return Gate::forUser($user)->inspect('update', $post);
    }
}

정책 클래스 커스터마이징

동일한 모델이라도 컨트롤러나 상황에 따라 서로 다른 인가 규칙이 적용되는 경우가 흔합니다. 기본적으로 정책은 Laravel의 내장 기능을 통해 결정됩니다. 하지만 특정 컨트롤러에서 특정 정책을 사용하고 싶다면 protected $policy 또는 protected $parentPolicy 변수를 알맞게 설정하세요.

모델 컨트롤러

<?php

namespace App\Http\Controllers\Api;

use App\Models\Post;
use App\Policies\CustomPostPolicy;

class PostsController extends ApiController
{
    /**
     * @var string $model
     */
    protected $model = Post::class;

    /**
     * @var string $policy
     */
    protected $policy = CustomPostPolicy::class;
}

연관관계 컨트롤러

<?php

namespace App\Http\Controllers\Api;

use App\Models\Team;
use App\Policies\CustomPostPolicy;
use App\Policies\CustomTeamPolicy;
use Orion\Http\Controllers\RelationController;

class TeamPostsController extends RelationController
{
     /**
     * @var string $model
     */
    protected $model = Team::class; // 또는 "App\Models\Team"
    
    /**
     * Post 모델에 정의된 관계 이름
     */
    protected $relation = 'posts';

    /**
     * @var string $parentPolicy
     */
    protected $parentPolicy = CustomTeamPolicy::class;

   /**
     * @var string $policy
     */
    protected $policy = CustomPostPolicy::class;
}

유효성 검사

요청 클래스는 Illuminate\Foundation\Http\FormRequest가 아니라 반드시Orion\Http\Requests\Request 클래스를 상속해야 합니다.

storeupdate 엔드포인트로 들어오는 요청 데이터의 유효성을 검사하기 위해, Orion은 다음 클래스명 패턴에 따라 리소스 모델의 요청 클래스를 찾습니다: App\Http\Requests\<model>Request.

예를 들어 App\Models\Message 모델이 있다면, 해당 요청 클래스는 App\Http\Requests\MessageRequest가 됩니다.

앱의 요청 클래스명이 이 명명 규칙을 따르지 않거나 더 명시적으로 지정하고 싶다면, 컨트롤러의 protected $request 속성에 전체 네임스페이스를 포함한 요청 클래스명을 설정하세요.

<?php

namespace App\Http\Controllers\Api;

use App\Models\Message;
use App\Http\Requests\CustomMessageRequest;

class MessagesController extends ApiController
{
    /**
     * @var string $model
     */
    protected $model = Message::class;

    /**
    * @var string $request
    */
    protected $request = CustomMessageRequest::class;
}

이후 요청 클래스는 Laravel 서비스 컨테이너를 통해 바인딩되며, 메서드 시그니처에 명시적으로 지정했을 때와 동일한 방식으로 storeupdate 메서드에서 요청 데이터의 유효성을 검사하는 데 사용됩니다:

public function store(CustomMessageRequest $request)
{
    ...
}

유효성 검사 규칙

storeupdate 작업의 규칙 정의

Orion이 제공하는 Orion\Http\Requests\Request 클래스에는 유효성 검사 규칙을 지정하기 위한 여러 메서드가 있습니다.

storeupdate 엔드포인트에 공통으로 적용되는 규칙은 commonRules 메서드로 정의할 수 있습니다. 특정 엔드포인트에만 적용되는 규칙을 정의하려면 storeRulesupdateRules 메서드를 사용하세요.

storeRulesupdateRules 메서드에 지정한 특정 필드의 규칙은, 동일한 키가 양쪽에 존재하는 경우 commonRules 메서드의 규칙을 덮어씁니다.
<?php

namespace App\Http\Requests;

use Orion\Http\Requests\Request;

class PostRequest extends Request
{
    public function commonRules() : array
    {
        return [
            'title' => 'required'
        ];
    }

    public function storeRules() : array
    {
        return [
            'status' => 'required|in:draft,review'
        ];
    }
}

이 예시에서 store 엔드포인트로 요청이 들어오면 titlestatus 필드가 모두 필수입니다. 반면 update 엔드포인트로 요청이 들어오면 title 필드만 필수입니다. updateRules 메서드에 별도의 규칙이 정의되어 있지 않고, title 필드는 commonRules 메서드에서 필수로 지정되어 있기 때문입니다.

연관관계 전용 작업의 규칙 정의

연관관계 전용 엔드포인트의 규칙도 정의할 수 있습니다: associateRules, attachRules, detachRules, syncRules, toggleRules, updatePivotRules.

이들 메서드에 지정한 규칙은 commonRules 메서드의 규칙과 병합되지 않습니다.

일괄 작업의 규칙 정의

일괄 작업 엔드포인트의 규칙도 정의할 수 있습니다: batchStoreRules, batchUpdateRules.

유효성 검사 메시지

특정 엔드포인트의 규칙을 설정할 수 있는 것과 마찬가지로, 유효성 검사 메시지도 커스터마이징할 수 있습니다.

storeupdate 작업의 유효성 검사 메시지 커스터마이징

storeupdate 엔드포인트에 공통으로 적용되는 메시지는 commonMessages 메서드로 정의할 수 있습니다. 특정 엔드포인트에만 적용되는 메시지를 정의하려면 storeMessagesupdateMessages 메서드를 사용하세요.

storeMessagesupdateMessages 메서드에 지정한 특정 필드의 메시지는, 동일한 키가 양쪽에 존재하는 경우 commonMessages 메서드의 메시지를 덮어씁니다.

연관관계 전용 작업의 유효성 검사 메시지 커스터마이징

연관관계 전용 엔드포인트의 메시지도 커스터마이징할 수 있습니다: associateMessages, attachMessages, detachMessages, syncMessages, toggleMessages, updatePivotMessages.

이들 메서드에 지정한 메시지는 commonMessages 메서드의 메시지와 병합되지 않습니다.

일괄 작업의 유효성 검사 메시지 커스터마이징

일괄 작업 엔드포인트의 메시지도 커스터마이징할 수 있습니다: batchStoreMessages, batchUpdateMessages.

요청 데이터 가져오기

기본적으로 엔티티를 저장하거나 수정할 때 모든 요청 데이터가 조회되어 모델의 fill 메서드에 전달됩니다.

하지만 유효성 검사를 통과한 데이터만 전달하도록 할 수도 있습니다. 이를 위해서는 orion.php 설정 파일에서 use_validatedtrue로 설정하세요.