素晴らしいコミュニティモジュール

fib-app

fibjsアプリケーションの基本的なapiフレームワーク

インストール

1
npm install fib-app [--save]

テスト

1
npm test

基本的なスクリプトを作成する

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
const http = require('http'); const util = require('util') const Session = require('fib-session') const App = require('../'); var app = new App('sqlite:test.db', { uuid: true }); app.db.use(require('./defs/person')); var session = new Session(new util.LruCache(20000), { timeout: 60 * 1000 }); var svr = new http.Server(8080, [ session.cookie_filter, { '/1.0': app } ]); svr.run();

その中で、 personはモデル定義モジュールであり、内容は次のとおりです。

1 2 3 4 5 6 7
module.exports = db => { db.define('person', { name: String, sex: ["male", "female"], age: Number }); };

これは標準のorm定義であり、タイプチェック、イベントなど、ormの他の機能も使用できます。

APIデータ形式

POSTおよびPUTリクエストの場合、リクエストの本文はJSON形式である必要があり、HTTPヘッダーのContent-Typeはapplication / jsonに設定する必要があります。

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"name": "tom","sex":"male","age":23}' \ http://localhost/1.0/person/57fbbdb0a2400000

すべての要求について、応答形式はJSONオブジェクトです。

リクエストの成功は、HTTPステータスコードによって示されます。 2XXステータスコードは成功を示し、4XXはリクエストの失敗を示します。リクエストが失敗した場合でも、レスポンスの本文はJSONオブジェクトのままですが、デバッグに使用できるコードとメッセージの2つのフィールドが常に含まれます。たとえば、権限認証の要求が失敗した場合、次の情報が返されます。

1 2 3 4
{ "code": 4030501, "message": "The operation isn’t allowed for clients due to class-level permissions." }

コードは3つの部分に分かれています。最初の3桁の403はエラーの種類を示し、05はデータテーブル番号を示し、01は詳細なエラーコードを示します。

GETリクエストの場合、通常、オブジェクトデータが返されます。GETリクエストのアドレスによっては、オブジェクトまたはアレイが返される場合があります。といった:

1 2 3 4 5
{ "name": "tom", "sex": "male", "age": 23 }

または:

1 2 3 4 5 6 7 8 9 10 11 12
[ { "name": "tom", "sex": "male", "age": 23 }, { "name": "lily", "sex": "female", "age": 22 } ]

専門分野

オブジェクトデータには、特別な意味を持つ4つのフィールドがあり、APIを介して変更することはできません。それらはidupdatedAtcreatedAtcreatedByです。

idupdatedAtcreatedAt単一フィールドは、自動的に作成および変更されます。 createdByは、それ自体でタイプを指定する必要があります。

基本的なオブジェクトアクセスAPI

このデータ定義を完了すると、RESTapi仕様に準拠するインターフェイス呼び出しの完全なセットが直接得られます。

url方法アクション
/1.0/:className役職新しいオブジェクトを作成する
/1.0/:className/:id取得するオブジェクトの読み取り
/1.0/:className/:id PUTオブジェクトを変更する
/1.0/:className/:id削除オブジェクトを削除する
/1.0/:className取得するクエリオブジェクトリスト

新しいオブジェクトを作成する

新しいオブジェクトを作成するには、POSTリクエストをクラスのURLに送信する必要があります。このURLには、オブジェクト自体が含まれている必要があります。たとえば、上記のようにオブジェクトを作成するには、次のようにします。

1 2 3 4
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name": "tom","sex":"male","age":23}' \ http://localhost/1.0/person

作成が成功すると、HTTP応答は201 Createdになり、応答の本文は、新しいオブジェクトのobjectIdとcreatedAtタイムスタンプを含むJSONオブジェクトになります。

1 2 3 4
{ "createdAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }

オブジェクトの読み取り

オブジェクトを作成するときに、返されたヘッダーの場所にGETリクエストを送信することで、そのコンテンツを取得できます。たとえば、上記で作成したオブジェクトを取得するには、次のようにします。

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000

返される本文は、ユーザーが指定したすべてのフィールドに加えて、 createdAtupdatedAtおよびidフィールドを含むJSONオブジェクトです。

1 2 3 4 5 6 7 8
{ "name": "tom", "sex": "male", "age": 23, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }

フィールドリターンkeys設定することにより、カスタマイズされたコンテンツを返すことができます。コンテンツへのkeys ,セグメンテーションフィールド名の文字列:

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000?keys=name%2Csex

戻ります:

1 2 3 4
{ "name": "tom", "sex": "male" }

オブジェクトを変更する

オブジェクトの既存のデータを変更するには、オブジェクトの対応するURLにPUTリクエストを送信できます。指定していないキーは変更されないため、オブジェクトデータのサブセットのみを更新できます。たとえば、オブジェクトの年齢フィールドを変更してみましょう。

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"age": 25}' \ http://localhost/1.0/person/57fbbdb0a2400000

返されるJSONオブジェクトには、更新が発生した時刻を示すupdatedAtフィールドとidフィールドが含まれます。

1 2 3 4
{ "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }

オブジェクトを削除する

オブジェクトを削除するには、次のように、指定したオブジェクトのURLにDELETEリクエストを送信します。

1
curl -X DELETE http://localhost/1.0/person/57fbbdb0a2400000

クエリオブジェクトリスト

URLパラメータなしでクラスのURLにGETリクエストを送信することにより、一度に複数のオブジェクトを取得できます。以下は、単にすべてのユーザーを取得するためのものです。

1
curl -X GET http://localhost/1.0/person

戻り値は結果フィールドを含むJSONオブジェクトであり、その値はオブジェクトのリストです。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[ { "name": "tom", "sex": "male", "age": 23, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" }, { "name": "lily", "sex": "female", "age": 22, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400001" } ]

キーフィールドのカスタマイズ

オブジェクトクエリと同様に、リストをクエリするときにkeysを設定keysことで、返される結果に含まれるフィールドをカスタマイズできます。コンテンツのkeys ,セグメンテーションフィールド名の文字列、例:

1
curl -X GET http://localhost/1.0/person?keys=name%2Cage

nameage 2つのフィールドのみを返すように指定します。

ここでフィルター条件

クエリオブジェクトは、 whereパラメータの形式によって制限できます。

whereパラメータの値はJSONでエンコードする必要があります。つまり、実際に送信されるURLリクエストを見ると、最初にJSONでエンコードしてから、URLでエンコードする必要があります。 whereパラメータを使用する最も簡単な方法は、適切なキーと値を含めることです。たとえば、名前がtomのユーザーを検索する場合は、次のようにクエリを作成する必要があります。

1
curl -X GET http://localhost/1.0/person?where=%7B%22name%22%3A%22tom%22%7D

whereの値はurlencodeの後のJSON文字列で、内容は次のとおりです。 {"name":"tom"}

正確に所定の値、マッチングに加えて、このような封入などの比較方法をサポートします。 where whereパラメーターは、次のオプションをサポートします。

キー操作サンプル
eq等しい{"name":{"eq": "tom"}}または{"name": "tom"}
ne等しくない{"name":{"ne": "tom"}}
gt以上{"年齢":{"gt": "24"}}
gte以上以上{"age":{"gte": "24"}}
lt未満{"年齢":{"lt": "24"}}
lte以下{"年齢":{"lte": "24"}}
お気に入りファジークエリ{"name":{"like": "%m"}}
みたいではなくファジークエリ{"name":{"not_like": "%m"}}
の間に間隔の比較{"年齢":{"間":[22,25]}}
not_between間隔の比較{"年齢":{"not_between":[22,25]}}
列挙する{"name":{"in":["tom"、 "lily"]}}
ありませんで列挙する{"name":{"not_in":["tom"、 "lily"]}}
またはまたは操作{"または":[{"name": "tom"}、{"age":24}]}

スキップレコードをスキップ

skipオプションを使用すると、指定した数のレコードをスキップして、ページめくりの効果を実現できます。

1
curl -X GET http://localhost/1.0/person?skip=100

limitはレコード制限を返します

limitオプションを使用すると、返されるレコードの数を制限できます。有効なlimit数は1〜1000で、デフォルトは100です。

1
curl -X GET http://localhost/1.0/person?limit=100

orderはソート方法を指定します

orderオプションを使用して、返される結果セットの並べ替え方法を設定します。フィールド名の前に-が含まれている場合は、逆の順序になります。

1
curl -X GET http://localhost/1.0/person?order=-id

countは結果の総数を返します

リクエスト時にcount増やすと、指定されたコンテンツを返しながら、結果セットの総数を返すことができます。

1
curl -X GET http://localhost/1.0/person?count=1&limit=1

この時点で、返される結果には、 countresults 2つのフィールドが含まれ、それぞれ合計と結果が含まれます。

1 2 3 4 5 6 7 8 9 10 11 12 13
{ "count": 2, "results": [ { "name": "tom", "sex": "male", "age": 23, "createdAt": "2017-11-25T01:39:35.931Z", "updatedAt": "2017-11-25T01:39:35.931Z", "id": "57fbbdb0a2400000" } ] }

拡張オブジェクトを作成する

ormを介してhasOneとhasManyを定義することにより、オブジェクト間の関係を定義し、APIに反映させることができます。例:

1 2 3 4 5 6 7 8 9
module.exports = db => { var Person = db.models.person; var Pet = db.define('pet', { name: String }); Person.hasMany('pets', Pet); };

拡張オブジェクトアクセスAPI

以下は、拡張オブジェクトのAPI定義です。

url方法アクション
/1.0/:className/:id/:extendName PUT拡張オブジェクトを設定する
/1.0/:className/:id/:extendName役職拡張オブジェクトを作成する
/1.0/:className/:id/:extendName/:rid取得する拡張オブジェクトを読み取る
/1.0/:className/:id/:extendName/:rid PUT拡張オブジェクトを変更します
/1.0/:className/:id/:extendName/:rid削除拡張オブジェクトを削除します
/1.0/:className/:id/:extendName取得する拡張オブジェクトのリストを照会する

拡張オブジェクトを設定する

拡張オブジェクトの設定は、2つの独立したオブジェクト間の接続を確立することです。たとえば、トムは猫という名前のペットを採用しました。これは、次の操作で実現できます。

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"id": "57fbbdb0a2400007"}' \ http://localhost/1.0/person/57fbbdb0a2400000/pets

呼び出しでは、catのIDを本文で指定する必要があります。

拡張オブジェクトを作成する

拡張オブジェクトを直接作成することにより、オブジェクトの作成中にオブジェクト間の接続を確立できます。といった:

1 2 3 4
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name": "cat"}' \ http://localhost/1.0/person/57fbbdb0a2400000/pets

猫という名前のペットが作成され、トムとの関係が確立されます。

拡張オブジェクトを読み取る

拡張オブジェクトの読み取りは、ベースオブジェクトの読み取りと非常によく似ており、キーオプションもサポートしています。

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

拡張オブジェクトを変更する

拡張オブジェクトの読み取りは、ベースオブジェクトの読み取りと非常によく似ています。

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"name": "cat 1"}' \ http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

拡張オブジェクトを削除します

拡張オブジェクトを削除しても、オブジェクト自体は削除されませんが、オブジェクト間の関係が削除されるだけです。

1
curl -X DETELE http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

拡張オブジェクトのリストを照会する

拡張オブジェクトリストのクエリは、基本オブジェクトリストのクエリと非常によく似ており、キーや条件付きフィルタリングなどのオプションもサポートしています。

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets

ACL

モデルACLを定義することにより、データのアクセス許可を制御できます。といった:

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
const orm = require('fib-orm'); module.exports = db => { db.define('blog', { title: String, detail: Stringnote: String }, { ACL: function(session) { return { "*": { "*": false }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": true } } }; } }); };

モデルの定義時にACLが指定されていない場合は、デフォルトのアクセス許可を設定するのと同じです。

1 2 3 4 5
{ "*": { "*": true } }

本体

そこACL対象の説明、ユーザーの3種類がありid 、ユーザーのroleおよび*id 、特定のユーザーを表すrole一定の役割を持つユーザーを表し、 *すべてのユーザーが表しています。

本体説明優先度
id特定のユーザーID 1
役割ユーザーグループ名2
*すべて3

パーミッションをチェックするときは、最初に一致するid権限が一致し、指定されていない場合は、ユーザーのマッチングroleに対応する権限を、まだ指定され、それがどうかを見ると*場合権限、 *も指定されていない、権限がありません。

たとえば、上記のアクセス許可の構成では、 userユーザーグループは読み取り可能に指定され、ユーザー57fbbdb0a2400000はすべてのアクセス許可があり、他のユーザーにはアクセス許可がありません。

権限

ACLは、APIの動作に基づいて5種類の権限を分類します。

権限説明許可されるタイプ
作成するオブジェクトを作成するtrue / false /配列
読んだオブジェクトの読み取りtrue / false /配列
書くオブジェクトを変更するtrue / false /配列
削除オブジェクトを削除する真/偽
見つけるクエリオブジェクトリスト真/偽
*すべての権限に一致true / false /配列

アクセス許可は、アクセスを許可するにはtrueに、アクセスを禁止するにはfalseに、指定されたフィールドのみへのアクセスを許可するにはarrayに設定されます。 deletefindarray受け入れません。 arrayが設定されているtrue 、それはtrueと見なされtrue 。指定された権限が存在しない場合、同じプリンシパルの下の*権限と一致します。存在しない場合は、次の優先度でサブジェクトに再度クエリを実行します。

たとえば、上記の例で、 user titledetailのみを読むことを許可され、他の人がtitleを読むことができるように設定する必要がある場合は、次のように設定できます。

1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "*": { "*": false, "read": ['title'] }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": ['title', 'detail'] } } }

オブジェクトのアクセス許可

クラス全体の権限はモデルで設定されます。特定のオブジェクトの権限を設定する必要がある場合は、次のことを実現するようにOACLを設定できます。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
module.exports = db => { db.define('person', { name: String, sex: ["male", "female"], age: Number }, { ACL: function(session) { return { "*": { "*": false } } }, OACL: function(session) { var _acl = {}; if(this.id === session.id) _acl[session.id] = { "*": true }; return _acl; } }); };

この例では、訪問者がオブジェクト自身である場合、すべての操作が許可されます。それ以外の場合、すべての訪問は禁止されます。権限は、次の手順に従ってチェックされます。

  • person[57fbbdb0a2400000] => OACL
  • person => ACL

拡張オブジェクトのアクセス許可

拡張オブジェクトのアクセス許可制御は、基本オブジェクト許可に似ていますが、唯一の違いは、ACLで個別に指定する必要があることです。

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 32 33 34 35 36 37 38 39 40 41
module.exports = db => { var Person = db.define('person', { name: String, sex: ["male", "female"], age: Number },{ ACL: function(session) { return { "*": { "read": ['name', 'sex'], "extends": { "pets": { "read": true, "find": true } } } } }, OACL: function(session) { var _acl = {}; if(this.id === session.id) _acl[session.id] = { "*": true, "extends": { "pets": { "*": true } } }; return _acl; } }); var Pet = db.define('pet', { name: String }); Person.hasMany('pets', Pet); };

この定義では、誰でも個人情報のnamesex確認し、自分のpetsを自由に確認して検索できます。ユーザー自身が自分のすべてのデータを操作でき、自分のペット情報に対するすべての権利を持っています。

拡張オブジェクトのアクセス権限をチェックする場合、オブジェクト権限と拡張オブジェクト権限は別々にチェックされます。たとえば、次のリクエスト:

1
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007

権限は、次の手順に従ってチェックされます。

  • pets[57fbbdb0a2400007] => OACL
  • person[57fbbdb0a2400000] => OACL => extends => pets
  • person => ACL => extends => pets
  • pets => ACL

関数

モデルに対してAPIを定義でき、関数をカスタマイズすることで複雑なデータ操作を完了できます。

権限の大部分はACLによって制御でき、オブジェクトベースの権限を完了するための機能は必要ありません。関数を使用して、承認ステータスに基づいてさまざまなユーザーグループにアクセス許可を付与するなど、データベースのアクセス許可を完了することができます。また、複数のデータベースレコードを変更する必要があるなど、複数の変更。

データモデルを描く

データ定義が完了したら、 app.diagram()使用してデータモデルのsvg形式のクラス図app.diagram()描画し、それをファイルに保存して、次のような画像を取得できます。図