Tolles Community-Modul

fib-app

fibjs-Anwendungsbasis-API-Framework

Installieren

1
npm install fib-app [--save]

Prüfen

1
npm test

Erstellen Sie das 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();

Darunter personbefindet sich 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 andere Funktionen von Orm, wie z. B. Typprüfung, Ereignisse usw., können ebenfalls verwendet werden.

API-Datenformat

Bei POST- und PUT-Anforderungen muss der Text der Anforderung im JSON-Format vorliegen, und der Content-Type des HTTP-Headers muss auf application/json festgelegt werden.

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

Das Antwortformat für alle Anfragen ist ein JSON-Objekt.

Der Erfolg einer Anfrage wird durch den HTTP-Statuscode angezeigt. Ein Statuscode von 2XX zeigt einen Erfolg an, während ein 4XX anzeigt, dass die Anforderung fehlgeschlagen ist. Wenn eine Anfrage fehlschlägt, ist der Text der Antwort immer noch ein JSON-Objekt, enthält aber immer Code- und Nachrichtenfelder, die Sie zum Debuggen verwenden können. Wenn beispielsweise eine Autorisierungsanfrage 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 403 stellen den Fehlertyp dar, 05 stellt die Datenblattnummer dar und 01 stellt den detaillierten Fehlercode dar.

Bei einem GET-Request werden normalerweise Objektdaten zurückgegeben, je nach Adresse des GET-Requests kann es sich um ein Objekt oder ein Array handeln. 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 besonderen Bedeutungen, die nicht über die API geändert werden können. sind id, updatedAt, , createdAt, bzw. createdBy.

Darunter id, updatedAt, wird createdAtein einzelnes Feld automatisch erstellt und geändert. createdBySie müssen den Typ selbst angeben.

Basisobjektzugriffs-API

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

URL Methode Aktion
/1.0/:Klassenname POST neues Objekt erstellen
/1.0/:Klassenname/:ID ERHALTEN gelesenes Objekt
/1.0/:Klassenname/:ID STELLEN Objekt ändern
/1.0/:Klassenname/:ID LÖSCHEN Objekt löschen
/1.0/:Klassenname 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. Um beispielsweise das Objekt wie oben beschrieben 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-Antwort 201 Created, und der Hauptteil der Antwort ist ein JSON-Objekt, das die objectId und den createdAt-Zeitstempel des neuen Objekts enthält:

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

gelesenes Objekt

Wenn Sie ein Objekt erstellen, können Sie seinen Inhalt abrufen, indem Sie eine GET-Anforderung an den zurückgegebenen Location-Header senden. Um beispielsweise das oben erstellte Objekt zu erhalten:

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

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

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, keysder Inhalt ist eine Feldnamenzeichenfolge, die durch , ,getrennt ist:

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 Daten zu ändern, die ein Objekt bereits hat, können Sie eine PUT-Anforderung an die entsprechende URL des Objekts senden. Alle Schlüssel, die Sie nicht angeben, werden nicht geändert, sodass Sie nur eine Teilmenge der Daten des Objekts 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 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, senden Sie eine DELETE-Anfrage an die URL des angegebenen Objekts, zum Beispiel:

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

Objektliste abfragen

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

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

Der zurückgegebene Wert ist ein JSON-Objekt, das ein 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" } ]

Schlüsselfeldanpassung

Wie bei der Objektabfrage keyskönnen . keysDer Inhalt ist eine Reihe von Feldnamen, die durch ,getrennt sind, zum Beispiel:

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

gibt an, dass nur namedie ageFelder und zwei zurückgegeben werden.

wo filtern

Das Abfrageobjekt kann in Form von whereParametern .

whereDer Wert des Parameters sollte JSON-codiert sein. Das heißt, wenn Sie sich die eigentliche URL-Anforderung ansehen, sollte diese zuerst JSON-codiert und dann URL-codiert sein. Der einfachste Weg, einen whereParameter besteht darin, den richtigen Schlüssel und Wert einzuschließen. Wenn wir beispielsweise nach einem Benutzer namens Tom suchen wollten, würden wir die Abfrage wie folgt erstellen:

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

whereDer Wert von ist ein urlenkodierter JSON-String mit folgendem Inhalt:{"name":"tom"}

Neben der exakten Übereinstimmung mit einem bestimmten Wert werden auch whereVergleiche wie etwa enthält unterstützt. whereDer Parameter unterstützt 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 weniger als oder gleich {"Alter":{"lte":"24"}}
wie unscharfe Abfrage {"name":{"like":"%m"}}
nicht wie unscharfe Abfrage {"name":{"not_like":"%m"}}
zwischen Intervallvergleich {"Alter":{"zwischen":[22,25]}}
nicht zwischen Intervallvergleich {"Alter":{"nicht_zwischen":[22,25]}}
in aufzählen {"name":{"in":["tom","lily"]}}
nicht in aufzählen {"name":{"not_in":["tom","lily"]}}
oder ODER-Verknüpfung {"oder":[{"name":"tom"},{"alter":24}]}

überspringen Datensätze überspringen

Mit der skipOption 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 das Datensatzlimit zurück

Mit der limitOption können Sie die Anzahl der zurückgegebenen Datensätze begrenzen, limitdie gültige Zahl ist 1-1000, der Standardwert ist 100.

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

order gibt die Sortiermethode an

Stellen Sie über die orderOption die Sortiermethode der zurückgegebenen Ergebnismenge ein: Enthält der Feldname davor -, erfolgt die Sortierung in umgekehrter Reihenfolge.

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

count gibt die Gesamtzahl der Ergebnisse zurück

Auf Anfrage erhöhen Die Gesamtzahl der Ergebnismengen, countdie zusammen mit dem angegebenen Inhalt zurückgegeben werden können.

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

An diesem Punkt enthält das zurückgegebene Ergebnis countund resultszwei Felder, 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 kann die Zuordnung zwischen Objekten definiert und in der API wiedergegeben werden, 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); };

API für erweiterten Objektzugriff

Das Folgende ist die API-Definition des Erweiterungsobjekts:

URL Methode Aktion
/1.0/:Klassenname/:id/:Erweiterungsname STELLEN Erweiterungsobjekt setzen
/1.0/:Klassenname/:id/:Erweiterungsname POST Erweiterungsobjekt erstellen
/1.0/:className/:id/:extendName/:rid ERHALTEN gelesenes Erweiterungsobjekt
/1.0/:className/:id/:extendName/:rid STELLEN Erweiterungsobjekt ändern
/1.0/:className/:id/:extendName/:rid LÖSCHEN Erweiterungsobjekt löschen
/1.0/:Klassenname/:id/:Erweiterungsname ERHALTEN Fragen Sie die Liste der erweiterten Objekte ab

Erweiterungsobjekt setzen

Durch das Setzen eines Erweiterungsobjekts wird eine Beziehung zwischen zwei unabhängigen Objekten hergestellt. Zum Beispiel adoptiert Tom ein Haustier namens Katze, was durch die folgenden Operationen erreicht werden kann:

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 die ID von cat im Body angegeben werden.

Erweiterungsobjekt erstellen

Indem Sie ein Erweiterungsobjekt direkt erstellen, können Sie die Verbindung zwischen Objekten herstellen, während Sie das Objekt erstellen. 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 Tom zugeordnet.

gelesenes Erweiterungsobjekt

Das Lesen eines Erweiterungsobjekts ist dem Lesen eines Basisobjekts sehr ähnlich und unterstützt auch die Option keys:

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

Erweiterungsobjekt ändern

Das Lesen eines Erweiterungsobjekts ist dem Lesen eines Basisobjekts 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

Erweiterungsobjekt löschen

Das Löschen eines Erweiterungsobjekts löscht nicht das Objekt selbst, sondern löst nur die Beziehung zwischen den Objekten auf:

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

Fragen Sie die Liste der erweiterten Objekte ab

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

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

ACL

Datenberechtigungen können durch Definieren 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 Sie Model definieren, ohne ACL anzugeben, entspricht dies dem Festlegen von Standardberechtigungen:

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

Hauptkörper

Es gibt drei Arten von ACL-Subjektbeschreibungen: user id, user roleund *, die ideinen bestimmten Benutzer, einen Benutzer rolemit einer bestimmten Rolle und *alle Benutzer darstellen:

Hauptkörper beschreiben Priorität
Ich würde bestimmte Benutzer-ID 1
Rolle Benutzergruppenname 2
* alle 3

Bei der Überprüfung der Berechtigungen wird zuerst mit den identsprechenden Berechtigungen abgeglichen. Wenn es nicht angegeben ist, wird es mit roleden Berechtigungen des Benutzers übereinstimmen. Wenn es noch angegeben ist, prüfen Sie, ob *die Berechtigungen von angegeben sind. Wenn *es nicht angegeben ist, gibt es keine Erlaubnis.

Die obige Berechtigungskonfiguration gibt beispielsweise an, dass die userBenutzergruppe lesen kann, der Benutzer 57fbbdb0a2400000alle Berechtigungen hat und andere Benutzer keine Berechtigungen haben.

Genehmigung

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

Genehmigung beschreiben Typ zulassen
schaffen Objekt erstellen wahr/falsch/Array
lesen gelesenes Objekt wahr/falsch/Array
schreiben Objekt ändern wahr/falsch/Array
löschen Objekt löschen wahr falsch
finden Objektliste abfragen wahr falsch
* stimmen mit allen Berechtigungen überein wahr/falsch/Array

Berechtigungen werden formuliert, um den Zugriff truezu erlauben, den Zugriff zufalse verbieten, den Zugriff nur auf bestimmte Felder zu erlauben. und werden nicht akzeptiert und als gesetzt behandelt . Wenn die angegebene Berechtigung nicht vorhanden ist, stimmt sie mit den Berechtigungen . Wenn keine vorhanden sind, fragen Sie das Thema der nächsten Priorität erneut ab.arraydeletefindarrayarraytrue*

Wenn Sie beispielsweise im obigen Beispiel usernur das Lesen zulassen titleund festlegen müssen detail, können andere lesen 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 Berechtigungen der gesamten Klasse werden für das Modell festgelegt. Wenn Sie Berechtigungen für bestimmte Objekte festlegen müssen, können Sie die OACL so festlegen, dass Folgendes erreicht wird:

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 Operationen erlaubt, andernfalls ist jeglicher Zugriff verboten. Berechtigungen werden wie folgt geprüft:

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

Erweiterte Objektberechtigungen

Die Zugriffskontrolle des erweiterten Objekts ähnelt der des Basisobjekts, der einzige Unterschied besteht darin, dass sie separat in der ACL 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 sexüberprüfen und seine persönlichen Informationen frei überprüfen und suchen. Der petsBenutzer selbst kann alle seine eigenen Daten verwalten und alle Berechtigungen für seine eigenen Haustierinformationen haben.

Bei der Prüfung von Zugriffsrechten für erweiterte Objekte werden Objektrechte und erweiterte Objektrechte 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

APIs können für Modelle definiert werden, und komplexe Datenoperationen können durch Anpassen von Funktionen durchgeführt werden.

Die überwiegende Mehrheit der Berechtigungen kann von ACL gesteuert werden, und objektbasierte Berechtigungen müssen nicht über Function erfolgen. Die Funktion kann verwendet werden, um datenbasierte Berechtigungen zu vervollständigen, z. B. das Erteilen von Berechtigungen für verschiedene Benutzergruppen basierend auf dem Genehmigungsstatus. Und eine Reihe von Modifikationen, wie z. B. die Notwendigkeit, mehrere Datenbankeinträge zu ändern.

Zeichnen Sie das Datenmodell

Nach Abschluss der Datendefinition können Sie das Datenmodell app.diagram()mithilfe des svgKlassendiagramms formatieren und in einer Datei speichern, um ein Bild ähnlich dem folgenden zu erhalten: Diagramm