Tolles Community-Modul

fib-app

Grundlegendes API-Framework für die fibjs-Anwendung

Installieren

1
npm install fib-app [--save]

Prüfen

1
npm test

Erstellen Sie ein Basisskript

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

Wo personist das Modelldefinitionsmodul, der Inhalt ist 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, und Sie können auch andere ORM-Funktionen verwenden, z. B. Typprüfung, Ereignisse usw.

API-Datenformat

Für POST- und PUT-Anfragen muss der Anfragetext im JSON-Format vorliegen und der Content-Type des HTTP-Headers muss auf application/json gesetzt 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 Anfragen ist das Antwortformat ein JSON-Objekt.

Ob eine Anfrage erfolgreich war oder nicht, wird durch den HTTP-Statuscode angezeigt. Ein 2XX-Statuscode zeigt einen Erfolg an, während ein 4XX-Statuscode angibt, dass die Anfrage fehlgeschlagen ist. Wenn eine Anfrage fehlschlägt, ist der Antworttext immer noch ein JSON-Objekt, enthält jedoch immer die Code- und Nachrichtenfelder, die Sie zum Debuggen verwenden können. Wenn beispielsweise eine Anfrage zur Berechtigungsauthentifizierung 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 Codecode ist in drei Teile unterteilt: Die ersten drei Ziffern 403 stellen den Fehlertyp dar, 05 stellt die Datenblattnummer dar und 01 stellt den detaillierten Fehlercode dar.

Bei GET-Anfragen werden in der Regel Objektdaten zurückgegeben. Abhängig von der Adresse der GET-Anfrage 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 } ]

Spezialgebiete

In den Objektdaten gibt es vier Felder mit besonderer Bedeutung, die nicht über die API geändert werden dürfen. Sie sind id, updatedAt, bzw. .createdAtcreatedBy

Darunter werden einzelne Felder automatisch erstellt und geändert id. Sie müssen den Typ selbst angeben.updatedAtcreatedAtcreatedBy

Grundlegende Objektzugriffs-API

Nach Abschluss einer solchen Datendefinition verfügen Sie direkt über eine Reihe von Schnittstellenaufrufen, die der REST-API-Spezifikation entsprechen:

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

Neues Objekt erstellen

Um ein neues Objekt zu erstellen, sollte eine POST-Anfrage an die URL der Klasse gesendet werden, die das Objekt selbst enthalten sollte. Um beispielsweise das oben gezeigte Objekt zu erstellen:

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, lautet die HTTP-Rückgabe 201 Created und der Hauptteil der Antwort ist ein JSON-Objekt, das die Objekt-ID und den Zeitstempel „createdAt“ 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-Anfrage an den Standort im zurückgegebenen Header senden. Um beispielsweise das oben erstellte Objekt abzurufen:

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

Der zurückgegebene Text ist ein JSON-Objekt, das alle vom Benutzer bereitgestellten Felder sowie die Felder createdAt, updatedAtund enthält:id

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 Festlegen des Rückgabefelds keyskönnen Sie den zurückgegebenen Inhalt anpassen, keysbei dem es sich um eine ,Zeichenfolge von Feldnamen handelt, die durch Folgendes getrennt sind:

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 vorhandenen Daten eines Objekts zu ändern, können Sie eine PUT-Anfrage an die entsprechende URL des Objekts senden. Alle nicht angegebenen Schlüssel werden nicht geändert, sodass Sie nur eine Teilmenge der Objektdaten aktualisieren können. Lassen Sie uns beispielsweise 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 updatedAtund idFelder, 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-Anfrage an die URL des angegebenen Objekts senden, zum Beispiel:

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

Objektliste abfragen

Sie können mehrere Objekte gleichzeitig abrufen, indem Sie eine GET-Anfrage ohne URL-Parameter an die URL der Klasse senden. So erhalten Sie einfach alle Benutzer:

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

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

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 der Schlüsselfelder

Wie bei der Objektabfrage können Sie keysdie in den zurückgegebenen Ergebnissen enthaltenen Felder anpassen, indem Sie sie beim Abfragen der Liste festlegen. keysDer Inhalt ist eine ,Zeichenfolge von Feldnamen, die durch getrennt sind, zum Beispiel:

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

Gibt an, dass nur die Felder „ nameund“ agezurückgegeben werden.

wo Filterbedingung

whereDas Abfrageobjekt kann in Form von Parametern eingeschränkt werden.

whereDer Parameterwert sollte JSON-codiert sein. Das heißt, wenn Sie sich die tatsächlich gestellte URL-Anfrage ansehen, sollte diese zuerst JSON-codiert und dann URL-codiert sein. Die einfachste whereMöglichkeit, Parameter zu verwenden, besteht darin, den entsprechenden Schlüssel und Wert einzuschließen. Wenn wir beispielsweise nach Benutzern namens Tom suchen möchten, würden wir die Abfrage wie folgt aufbauen:

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

whereDer Wert ist eine URL-kodierte JSON-Zeichenfolge, der Inhalt ist:{"name":"tom"}

Neben der genauen Übereinstimmung mit einem bestimmten Wert wherewerden auch Vergleichsmethoden wie die Einbeziehung unterstützt. whereParameter unterstützen die folgenden Optionen:

Schlüssel Betrieb Probe
Gl gleich {"name":{"eq": "tom"}} oder {"name": "tom"}
ne Nicht gleichzusetzen mit {"name":{"ne":"tom"}}
gt mehr als die {"Alter":{"gt":24"}}
gte größer oder gleich {"Alter":{"gte":24"}}
lt weniger als {"Alter":{"lt":24"}}
lte Gleich oder kleiner als {"Alter":{"lte":24"}}
wie Fuzzy-Abfrage {"name":{"like":%m"}}
nicht wie Fuzzy-Abfrage {"name":{"not_like":"%m"}}
zwischen Intervallvergleich {"Alter":{"zwischen":[22,25]}}
nicht zwischen Intervallvergleich {"age":{"not_between":[22,25]}}
In aufzählen {"name":{"in":["tom","lily"]}}
nicht in aufzählen {"name":{"not_in":["tom",lily"]}}
oder ODER-Verknüpfung {"or":[{"name":"tom"},{"age":24}]}

überspringen Datensätze überspringen

Mit skipdieser Option können Sie die angegebene Anzahl von Datensätzen überspringen, um den Effekt des Umblätterns zu erzielen.

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

limit gibt Datensatzlimit zurück

Mit limitdieser Option können Sie die Anzahl der zurückgegebenen Datensätze begrenzen. limitDie gültigen Zahlen sind 1-1000 und der Standardwert ist 100.

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

order gibt die Sortiermethode an

Verwenden Sie orderdie Option, um die Sortiermethode des zurückgegebenen Ergebnissatzes festzulegen. Wenn der Feldname davor steht, -ist die Reihenfolge umgekehrt.

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

count gibt die Gesamtzahl der Ergebnisse zurück

Auf Anfrage erhöht. countDie Gesamtzahl der Ergebnismengen, die zurückgegeben werden können, während der angegebene Inhalt zurückgegeben wird.

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

Zu diesem Zeitpunkt enthält das zurückgegebene Ergebnis zwei Felder: countund results, die die Gesamtzahl bzw. das Ergebnis enthalten:

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 die Definition von hasOne und hasMany über ORM können Sie die Zuordnung zwischen Objekten definieren und in der API widerspiegeln, zum Beispiel:

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

Das Folgende ist die API-Definition des Erweiterungsobjekts:

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

Erweiterungsobjekt festlegen

Durch das Festlegen eines Erweiterungsobjekts wird eine Beziehung zwischen zwei unabhängigen Objekten hergestellt. Wenn Tom beispielsweise ein Haustier namens Katze adoptiert, kann er dies mit den folgenden Vorgängen erreichen:

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

Beim Aufruf muss im Textkörper die ID der Katze angegeben werden.

Erweiterungsobjekt erstellen

Durch das direkte Erstellen erweiterter Objekte können beim Erstellen von Objekten Verbindungen zwischen Objekten hergestellt werden. 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.

Erweiterungsobjekt lesen

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

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

Erweiterungsobjekt ändern

Das Lesen erweiterter Objekte ist dem Lesen von Basisobjekten sehr ähnlich:

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

Erweitertes Objekt löschen

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

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

Erweiterte Objektliste abfragen

Das Abfragen der erweiterten Objektliste ist dem Abfragen der Basisobjektliste sehr ähnlich und unterstützt auch Optionen wie Schlüssel und bedingte Filterung:

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

ACL

Datenberechtigungen können durch die Definition der ACL des Modells 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: Stringnote: String }, { ACL: function(session) { return { "*": { "*": false }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": true } } }; } }); };

Wenn beim Definieren des Modells keine ACL angegeben wird, entspricht dies dem Festlegen der Standardberechtigungen:

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

Hauptkörper

Es gibt drei Arten von ACL-Betreffbeschreibungen: Benutzer id, Benutzer roleund *, iddie einen bestimmten Benutzer, roleBenutzer mit einer bestimmten Rolle und *alle Benutzer darstellen:

Hauptkörper beschreiben Priorität
AUSWEIS spezifische Benutzer-ID 1
Rolle Name der Benutzergruppe 2
* Alle 3

Bei der Überprüfung der Berechtigungen wird zunächst mit idden entsprechenden Berechtigungen abgeglichen. Wenn nicht angegeben, dann mit roleden entsprechenden Berechtigungen des Benutzers abgeglichen. Wenn noch angegeben, prüfen Sie, ob *die Berechtigungen angegeben sind. Wenn *nicht angegeben, ist keine Berechtigung vorhanden.

In der obigen Berechtigungskonfiguration wird beispielsweise userangegeben, dass die Benutzergruppe lesen darf. Der Benutzer 57fbbdb0a2400000hat alle Berechtigungen, andere Benutzer haben jedoch keine Berechtigungen.

Berechtigungen

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

Berechtigungen beschreiben zulässige Typen
erstellen Objekt erstellen wahr/falsch/Array
lesen Objekt lesen wahr/falsch/Array
schreiben Objekt ändern wahr/falsch/Array
löschen Objekt löschen wahr falsch
finden Objektliste abfragen wahr falsch
* Passen Sie alle Berechtigungen an wahr/falsch/Array

Berechtigungen werden so festgelegt true, dass sie den Zugriff erlauben, falseden Zugriff verweigern und arraynur den Zugriff auf bestimmte Felder erlauben. deleteund findwerden nicht akzeptiert und gleich behandelt, arraywenn sie gesetzt sind . Wenn die angegebene Berechtigung nicht vorhanden ist, werden die Berechtigungen unter demselben Betreff abgeglichen. Wenn keines von beiden vorhanden ist, fragen Sie den Betreff der nächsten Prioritätsstufe erneut ab.arraytrue*

Wenn Sie beispielsweise im obigen Beispiel „ userNur Lesen“ festlegen titleund detailanderen das Lesen erlauben möchten title, können Sie dies wie folgt festlegen:

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 für das Modell festgelegten Berechtigungen sind die Berechtigungen der gesamten Klasse. Wenn Sie Berechtigungen für bestimmte Objekte festlegen müssen, können Sie dies tun, 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; } }); };

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

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

Erweiterte Objektberechtigungen

Die Zugriffsberechtigungssteuerung von erweiterten Objekten ähnelt den Berechtigungen 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 die nameSumme der persönlichen Informationen überprüfen sexund sie frei überprüfen und durchsuchen pets. Der Benutzer selbst kann alle seine eigenen Daten verwalten und hat volle Berechtigungen für seine eigenen Haustierinformationen.

Bei der Prüfung der Zugriffsberechtigungen für erweiterte Objekte werden Objektberechtigungen und erweiterte Objektberechtigungen separat geprüft. Zum Beispiel die folgende Anfrage:

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

Berechtigungen werden wie folgt geprüft:

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

Funktion

Für das Modell können APIs definiert werden und komplexe Datenoperationen können über benutzerdefinierte Funktionen abgeschlossen werden.

Die meisten Berechtigungen können über ACL gesteuert werden, und objektbasierte Berechtigungen müssen nicht über die Funktion implementiert werden. Die Funktion kann zum Vervollständigen datenbasierter Berechtigungen verwendet werden, z. B. zum Erteilen von Berechtigungen für verschiedene Benutzergruppen basierend auf dem Genehmigungsstatus. Und mehrere Änderungen, z. B. die Notwendigkeit, mehrere Datenbankeinträge zu ändern.

Datenmodell zeichnen

Nach Abschluss der Datendefinition können Sie app.diagram()das Formatklassendiagramm des Datenmodells zeichnen svg. Beim Speichern in einer Datei erhalten Sie ein Bild ähnlich dem folgenden: Diagramm