Fantastisches Community-Modul

fib-app

Fibjs Application Base API Framework

Installieren

1
npm install fib-app [--save]

Test

1
npm test

Erstellen des Basisskripts

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();

Wenn person das Modelldefinitionsmodul ist, lautet der Inhalt wie folgt:

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

Dies ist eine Standard-ORM-Definition. Es können auch andere ORM-Funktionen verwendet werden, z. B. Typprüfung, Ereignisse usw.

API-Datenformat

Bei POST- und PUT-Anforderungen muss der Hauptteil der Anforderung im JSON-Format vorliegen und der Inhaltstyp des HTTP-Headers muss auf application / json festgelegt sein.

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

Für alle Anforderungen ist das Antwortformat ein JSON-Objekt.

Der Erfolg einer Anfrage wird durch den HTTP-Statuscode angezeigt. Ein 2XX-Statuscode zeigt Erfolg an, und ein 4XX zeigt an, dass die Anforderung fehlgeschlagen ist. Wenn eine Anforderung fehlschlägt, ist der Hauptteil der Antwort immer noch ein JSON-Objekt, enthält jedoch immer die Code- und Nachrichtenfelder, die Sie zum Debuggen verwenden können. Wenn beispielsweise eine Anforderungsberechtigungsauthentifizierung fehlschlägt, werden die folgenden Informationen zurückgegeben:

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

Der Code ist in drei Teile unterteilt: Die ersten drei Ziffern geben den Fehlertyp an, 05 die Datentabellennummer und 01 den detaillierten Fehlercode.

Bei GET-Anforderungen werden normalerweise Objektdaten zurückgegeben. Abhängig von der Adresse der GET-Anforderung kann ein Objekt oder ein Array zurückgegeben werden. Zum Beispiel:

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

Oder:

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

Spezialgebiet

In den Objektdaten gibt es vier spezielle Bedeutungsfelder, die nicht über die API geändert werden können. Sie sind id , updatedAt , createdAt , createdBy .

Darunter id , updatedAt , createdAt ein einzelnes Feld automatisch erstellt und geändert. createdBy muss den Typ selbst angeben.

Basisobjektzugriffs-API

Nach Abschluss dieser Datendefinition verfügen Sie über einen vollständigen Satz von Schnittstellenaufrufen, die der REST-API-Spezifikation entsprechen:

URL Methode Aktion
/1.0/:className POST Neues Objekt erstellen
/1.0/:className/:id ERHALTEN Objekt lesen
/1.0/:className/:id PUT Objekt ändern
/1.0/:className/:id LÖSCHEN Objekt löschen
/1.0/:className ERHALTEN Objektliste abfragen

Neues Objekt erstellen

Um ein neues Objekt zu erstellen, sollte eine POST-Anforderung an die URL der Klasse gesendet werden, die das Objekt selbst enthalten sollte. So erstellen Sie beispielsweise ein Objekt wie folgt:

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

Wenn die Erstellung erfolgreich ist, gibt HTTP 201 Created zurück, und der Hauptteil der Antwort ist ein JSON-Objekt, das die Objekt-ID und den Erstellungszeitpunkt des neuen Objekts enthält:

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

Objekt lesen

Wenn Sie ein Objekt erstellen, können Sie dessen Inhalt abrufen, indem Sie eine GET-Anforderung an den Speicherort des zurückgegebenen Headers senden. Um beispielsweise das oben erstellte Objekt abzurufen:

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

Der Körper gibt ein JSON - Objekt - Feld enthält alle Benutzer und createdAt , updatedAt und id Felder:

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" }

Durch die Einstellung Feld kehrt keys , individuelle Inhalte können zurückgegeben werden keys zu einem Gehalt , Segmentierung Feldnamen Strings:

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

Wird zurückkehren:

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

Objekt ändern

Um die Daten zu ändern, über die ein Objekt bereits verfügt, können Sie eine PUT-Anforderung an die entsprechende URL des Objekts senden. Jeder von Ihnen nicht angegebene Schlüssel wird nicht geändert, sodass Sie nur eine Teilmenge der Objektdaten aktualisieren können. Lassen Sie uns zum Beispiel ein Altersfeld unseres Objekts ändern:

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

Das zurückgegebene JSON-Objekt enthält die Felder updatedAt und id , die angeben, wann die Aktualisierung stattgefunden hat:

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

Objekt löschen

Um ein Objekt zu löschen, können Sie eine DELETE-Anforderung an die URL des angegebenen Objekts senden, z.

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

Objektliste abfragen

Durch Senden einer GET-Anforderung an die URL der Klasse können Sie mehrere Objekte gleichzeitig ohne URL-Parameter abrufen. Hier ist eine einfache Möglichkeit, alle Benutzer zu erreichen:

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

Der zurückgegebene Wert ist ein JSON-Objekt, das das Ergebnisfeld enthält, und sein Wert ist eine Liste von Objekten:

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" } ]

Anpassung des Schlüsselfelds

Wie bei Objektabfragen können Sie die in den zurückgegebenen Ergebnissen enthaltenen Felder anpassen, indem Sie beim Abfragen der Liste keys festlegen. keys eines Inhalts zu , Segmentierung Feldnamen Zeichenketten, zum Beispiel:

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

Wird angegeben, um nur die Felder name und age .

wo Filter

Über die Form des where Parameters können Sie Einschränkungen für das Abfrageobjekt festlegen.

Der Wert des where Parameters sollte JSON-codiert sein. Wenn Sie sich also die tatsächlich ausgegebene URL-Anforderung ansehen, sollte diese zuerst JSON-codiert und dann URL-codiert werden. Der einfachste Weg, den where Parameter zu verwenden, besteht darin, den entsprechenden Schlüssel und Wert anzugeben. Wenn wir beispielsweise nach einem Benutzer namens tom suchen möchten, erstellen wir eine Abfrage wie folgt:

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

Der Wert von where ist eine JSON-Zeichenfolge nach urlencode. Der Inhalt lautet: {"name":"tom"}

Neben der exakten Übereinstimmung mit einem bestimmten Wert, where auch Vergleichsmethoden wie Einschluss unterstützt. where Parameter unterstützt die folgenden Optionen:

Schlüssel Betrieb Probe
Gl Gleich {"name": {"eq": "tom"}} oder {"name": "tom"}
ne Nicht gleich {"name": {"ne": "tom"}}
gt Größer als {"age": {"gt": "24"}}
gte Größer oder gleich {"age": {"gte": "24"}}
lt Weniger als {"age": {"lt": "24"}}
lte Kleiner als oder gleich {"age": {"lte": "24"}}
wie Fuzzy-Abfrage {"name": {"like": "% m"}}
nicht wie Fuzzy-Abfrage {"name": {"not_like": "% m"}}
zwischen Intervallvergleich {"Alter": {"zwischen": [22,25]}}
not_between Intervallvergleich {"age": {"not_between": [22,25]}}
in Aufzählung {"name": {"in": ["tom", "lily"]}}
not_in Aufzählung {"name": {"not_in": ["tom", "lily"]}}
oder ODER-Betrieb {"oder": [{"Name": "Tom"}, {"Alter": 24}]}

überspringen Datensätze überspringen

Mit der Option skip können Sie die angegebene Anzahl von Datensätzen überspringen und den Effekt des Umblätterns erzielen.

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

limit gibt das Datensatzlimit zurück

Mit der Option limit können Sie die Anzahl der zurückgegebenen Datensätze begrenzen. Die gültige Anzahl der limit beträgt 1-1000 und der Standardwert ist 100.

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

Reihenfolge gibt die Sortiermethode an

Durch die order Option, stellen Sie die Rückgabe von Ergebnismengen sortiert werden, bevor der Feldname enthält - wenn umgekehrt.

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

count gibt die Gesamtzahl der Ergebnisse zurück

Erhöhungs - Anforderung count die Gesamtzahl kann eine Ergebnismenge des angegebenen Inhalts zur gleichen Zeit zurück.

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

Zu diesem Zeitpunkt enthält das zurückgegebene Ergebnis zwei Felder, count und results , einschließlich der Summe und des Ergebnisses:

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" } ] }

Erweiterungsobjekt erstellen

Durch Definieren von hasOne und hasMany über orm können Sie die Zuordnung zwischen Objekten definieren und in der API wiedergeben, z. B.:

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); };

Erweiterte Objektzugriffs-API

Hier ist die API-Definition des Erweiterungsobjekts:

URL Methode Aktion
/1.0/:className/:id/:extendName PUT Erweiterungsobjekt festlegen
/1.0/:className/:id/:extendName POST Erweiterungsobjekt erstellen
/1.0/:className/:id/:extendName/:rid ERHALTEN Erweitertes Objekt lesen
/1.0/:className/:id/:extendName/:rid PUT Erweiterungsobjekte ändern
/1.0/:className/:id/:extendName/:rid LÖSCHEN Erweiterte Objekte löschen
/1.0/:className/:id/:extendName ERHALTEN Erweiterte Objektliste abfragen

Erweiterungsobjekt festlegen

Durch Festlegen eines erweiterten Objekts wird eine Beziehung zwischen zwei unabhängigen Objekten hergestellt. Zum Beispiel hat Tom ein Haustier namens cat adoptiert, das mit den folgenden Operationen implementiert werden kann:

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

Die ID der Katze muss im Anruf im Körper angegeben werden.

Erweiterungsobjekt erstellen

Durch direktes Erstellen erweiterter Objekte können Sie beim Erstellen Beziehungen zwischen Objekten herstellen. Zum Beispiel:

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

Ein Haustier namens Katze wird erstellt und mit Tom verknüpft.

Erweitertes Objekt lesen

Das Lesen erweiterter Objekte ähnelt dem Lesen von Basisobjekten und unterstützt auch die Schlüsseloption:

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

Erweiterungsobjekte ändern

Das Lesen erweiterter Objekte ähnelt dem Lesen von Basisobjekten:

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

Erweiterte Objekte löschen

Durch das Löschen eines erweiterten Objekts wird das Objekt selbst nicht gelöscht, sondern nur die Beziehung zwischen den Objekten freigegeben:

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

Erweiterte Objektliste abfragen

Die erweiterte Objektliste für Abfragen ähnelt der Objektliste für Abfragebasis. Sie unterstützt auch Optionen wie Schlüssel und Bedingungsfilterung:

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

ACL

Datenberechtigungen können durch Definieren von ACLs für Modelle gesteuert werden. Zum Beispiel:

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: String, note: String }, { ACL: function(session) { return { "*": { "*": false }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": true } } }; } }); };

Wenn Sie beim Definieren eines Modells keine ACL angeben, entspricht dies dem Festlegen von Standardberechtigungen:

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

Betreff

Es gibt drei Haupt ACL Beschreibung Benutzer id , Benutzer role , und * , id einen bestimmten Benutzer darstellt, role , dass der Benutzer eine Rolle hat, * steht für alle Benutzer:

Betreff Beschreibung Priorität
id Benutzerspezifische ID 1
Rolle Benutzergruppenname 2
* * Alle 3

Wenn Berechtigungen überprüft, müssen Sie zuerst übereinstimmen id entsprechen Berechtigungen , wenn nicht anders angegeben, Benutzer passende role Behörde entspricht, wenn noch angegeben, sieht es an , ob die * Behörde, wenn * ist auch nicht anders angegeben, haben keine Berechtigung.

In der obigen Berechtigungskonfiguration wird beispielsweise angegeben, dass die user lesen kann. Benutzer 57fbbdb0a2400000 verfügt über alle Berechtigungen, während andere Benutzer keine Berechtigungen haben.

Behörde

ACL klassifiziert Berechtigungen basierend auf dem API-Verhalten in fünf Kategorien:

Behörde Beschreibung Zulässige Typen
erstellen Objekt erstellen true / false / array
lesen Objekt lesen true / false / array
schreibe Objekt ändern true / false / array
löschen Objekt löschen wahr / falsch
finden Objektliste abfragen wahr / falsch
* * Alle Berechtigungen abgleichen true / false / array

Die Berechtigung wird auf true , um den Zugriff zuzulassen, false , um den Zugriff zu verhindern, und array , um den Zugriff nur auf bestimmte Felder zu ermöglichen. delete und find akzeptieren keine array . Wenn array ist, werden sie als true behandelt. Wenn die angegebene Berechtigung nicht vorhanden ist, stimmt sie mit der Berechtigung * unter demselben Prinzipal überein. Wenn keine vorhanden sind, fragen Sie den Betreff der nächsten Priorität erneut ab.

Wenn Sie im obigen Beispiel beispielsweise festlegen müssen, dass der user nur title und detail liest und andere title lesen können, können Sie dies folgendermaßen einstellen:

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

Objektberechtigungen

Die Berechtigungen der gesamten Klasse werden für das Modell festgelegt. Wenn Sie Berechtigungen für bestimmte Objekte festlegen müssen, können Sie dies erreichen, indem Sie OACL festlegen:

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; } }); };

In diesem Beispiel sind alle Vorgänge zulässig, wenn der Besucher selbst das Objekt ist, andernfalls ist jeglicher Zugriff verboten. Die Berechtigungen werden wie folgt überprüft:

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

Erweiterte Objektberechtigungen

Die Zugriffssteuerung erweiterter Objekte ähnelt der von Basisobjekten. Der einzige Unterschied besteht darin, dass die ACL separat angegeben werden muss:

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); };

In dieser Definition kann jeder den name und das sex persönlicher Informationen nachschlagen und frei nach seinen pets suchen. Der Benutzer selbst kann alle seine eigenen Daten manipulieren und hat alle Rechte, Haustierinformationen zu besitzen.

Bei der Überprüfung der Zugriffsrechte erweiterter Objekte werden die Objektberechtigungen und erweiterten Objektberechtigungen separat geprüft. Zum Beispiel die folgende Anfrage:

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

Die Berechtigungen werden wie folgt überprüft:

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

Funktion

Sie können APIs für Modelle definieren und für komplexe Datenoperationen mit benutzerdefinierten Funktionen vervollständigen.

Die meisten Berechtigungen können über ACLs gesteuert werden. Sie müssen keine Funktionen verwenden, um objektbasierte Berechtigungen abzuschließen. Mit dieser Funktion können datenbasierte Berechtigungen abgeschlossen werden, z. B. Berechtigungen für verschiedene Benutzergruppen basierend auf dem Genehmigungsstatus. Und mehrere Änderungen, z. B. die Notwendigkeit, mehrere Datenbankeinträge zu ändern.

Zeichnen Sie das Datenmodell

Nach Abschluss der Datendefinition, verwendet werden können app.diagram() Zeichendatenmodell svg - Format Klassendiagramm, wird die Datei in ein Bild ähnlich dem folgenden gespeichert werden: Diagramm