web-dev-qa-db-ja.com

役割ベースREST API?

REST APIを構築しています。このAPIを使用して、さまざまな役割を持つ複数のユーザーが、含まれているリソースにアクセスできます。

スコープを単純に保つために、「学生/教師/クラス」ドメインを取り上げましょう:

GET /studentsはアクセスするリソースです。

ユーザーには学生や教師のような役割があるかもしれません

学生はクラスの学生にのみアクセスできます。教師は、教えるクラスの生徒にアクセスできます。一部の用途は学生であり、他のクラスも教える場合があります。彼らは自分のクラスの生徒と彼らが教えるクラスの生徒にアクセスできる必要があります。

理想的には、これを2つの関数として実装したい-1つのロールにつき1つ、そしてユーザーが複数のロールを持っている場合は「ユニオン」。

私の質問は:これを実装するためにどのパターンを使用する必要がありますか?

外部

  • ロールごとにAPIを分割する必要がありますか? GET /teacher/studentsおよびGET /student/studentsそれは私には正しくないようです。
  • 私が1つのリソースであることをすべて維持する(推奨)

内部で

内部でどのように実装する必要がありますか?

  • すべての方法は、役割ごとにBIGスイッチから始める必要がありますか?
  • ロールごとにリポジトリを実装する必要がありますか?
  • これを達成するのに役立つデザインパターンはありますか?

余談ですが、私は ASP.NET Web API および Entity Framework 6 を使用していますが、概念的な実装では実際には問題になりません。

27
Casper Jensen

次のように、ロールではなく、リソースを中心にAPIを構築する必要があります。

/rest/students

生徒を見ることができる役割を持つ誰もがアクセスできる必要があります。

内部的には、ロールベースのセキュリティを実装しています。その方法は、アプリケーションの詳細によって異なりますが、たとえば、役割テーブルがあり、各人に1つ以上の役割があり、それらの役割が各人がアクセスできるものを決定するとします。生徒にアクセスするためのルールはすでに述べています。

  • 学生は、受講したクラスの学生にアクセスできます
  • 教師は自分が教えるクラスの生徒にアクセスできます

したがって、人が電話すると:

/rest/students

生徒にアクセスするメソッドを呼び出し、人の役割を渡します。ここにいくつかの擬似コードがあります:

roles = person.roles; //array
students = getStudents( roles );
return students;

そしてその方法では、別々の呼び出しで各役割の学生を得ることができます、例えば:

factory = getFactory();
classes= [];
students = [];
for( role in roles ){
    service = factory.getService( role );
    // implementation details of how you get classes for student/teacher are hidden in the service
    classes = classes.merge( service.getClasses( person ) );
    // classes[] has class.students[]
    // loop on classes and add each student to students, or send back classes with nested students? depends on use case
  }
}

これは、あなたができることについては非常に大雑把な考えであり、必ずしも特定のニーズに合うとは限りませんが、関係する部分の感覚を与えるはずです。各生徒をリストしたクラスを返却する場合は、これが良い方法です。学生だけが必要な場合は、各クラスから学生を抽出して、学生のコレクションに統合できます。

いいえ、役割ごとに個別のリポジトリを用意することはできません。すべての役割は、データの取得方法を決定することであり、データを使用して何ができるかを決定することです(たとえば、教師は生徒の成績を入力できます)。データ自体は同じです。

パターンに関しては、このアプローチはファクトリパターンを使用して、役割に基づいてデータを取得するサービスを抽象化します。役割ごとに個別のサービスを用意することが適切な場合とそうでない場合があります。この方法が好きなのは、プログラムの各段階でコードの量を最小限に抑え、スイッチやifブロックよりも読みやすくするためです。

12
Robert Munn

ペンと紙を見つけ、システムのモデリングを開始します。

PERSONというドメインエンティティが必要になる可能性があります。 STUDENTSとTEACHERの両方が "is-a" PERSONであるため、firstname、lastnameなどの一般的な属性を持つPERSONという抽象的なエンティティを作成できます。TEACHER-> is-a-> Person。これで、生徒には当てはまらない教師の特徴を見つけることができます。例えば教師は、1つ以上のSUBJECTに関してクラスを教えます。

セキュリティの適用は、アプリケーションの機能しない側面と見なされます。これは 分野横断的な懸念 であり、「ビジネスロジック」の外部で処理する必要があります。 @Robert Munnが指摘するように、ROLEはすべて1か所で管理する必要があります。ロールを使用して特定の機能へのアクセスを制限することはかなり粗く、その概念は ロールベースのアクセス制御 (RBAC)と呼ばれます。

教師が生徒の成績を見ることができるかどうかを確認するには、ドメインモデルで表現する必要があります。先生が主題のプログラミングに関するクラスを持っているとしましょう。おそらく、生徒がさまざまな科目のクラスに参加することをモデルで表現します。これが、アプリケーション/ビジネスロジックの中心です。これは、テスト駆動開発を使用して検証できるロジックです。

リソースを分割してすべきアプリケーションをテスト可能かつモジュール式にします。

とにかく、私が何を意味するかを実際に示す最善の方法は、コードでそれを示すことです:)これがGitHubページです: https://github.com/thomasandersen77/role-based-rest-api

幸運を :)

0
Thomas Andersen