Fantastisches Community-Modul

fib-app

Fibjs Application Basic API Framework

Installieren

1
npm install fib-app [--save]

Prüfung

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

Unter ihnen ist die person das Modelldefinitionsmodul mit folgendem Inhalt:

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 können ebenfalls 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 einen Fehler der Anforderung an. Wenn eine Anforderung fehlschlägt, ist der Hauptteil der Antwort immer noch ein JSON-Objekt, enthält jedoch immer zwei Felder, Code und Nachricht, die Sie zum Debuggen verwenden können. Wenn beispielsweise eine Anforderung 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 Code ist in drei Teile unterteilt: Die ersten drei Ziffern 403 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. sowie:

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

Spezielles Feld

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

Die einzelnen Felder id , updatedAt , createdAt werden automatisch erstellt und geändert. createdBy muss den Typ selbst angeben.

Grundlegende Objektzugriffs-API

Nach Abschluss dieser Datendefinition erhalten Sie direkt eine Reihe von Schnittstellenaufrufen, die der REST-API-Spezifikation entsprechen:

URL Methode Aktion
/1.0/:className POST Neues Objekt erstellen
/1.0/:className/:id BEKOMMEN Objekt lesen
/1.0/:className/:id STELLEN Objekt ändern
/1.0/:className/:id LÖSCHEN Objekt löschen
/1.0/:className BEKOMMEN 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 das Objekt wie oben beschrieben:

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 Erstellt, und der Hauptteil der Antwort ist ein JSON-Objekt, einschließlich der Objekt-ID und des erstellten Zeitstempels des neuen Objekts:

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 zurück Körper ist ein JSON Objekt enthält alle vom Benutzer bereitgestellten Felder sowie 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 vorhandenen Daten eines Objekts zu ändern, 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. Das Folgende dient einfach dazu, 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 der Objektabfrage können Sie die im zurückgegebenen Ergebnis enthaltenen Felder anpassen, indem Sie beim Abfragen der Liste keys festlegen. keys eines Inhalts , Segmentierungsfeldnamenzeichenfolgen, zum Beispiel:

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

Gibt an, dass nur zwei Felder name und age .

wo Filterbedingung

Das Abfrageobjekt kann in Form des Parameters where werden.

Der Wert des where Parameters sollte JSON-codiert sein. Mit anderen Worten, wenn Sie sich die tatsächlich gesendete URL-Anfrage ansehen, sollte sie 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 Benutzern suchen möchten, deren Name tom ist, sollten wir die Abfrage folgendermaßen erstellen:

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 Operation Stichprobe
Gl gleich {"name": {"eq": "tom"}} oder {"name": "tom"}
ne Nicht gleichzusetzen mit {"name": {"ne": "tom"}}
gt mehr als die {"age": {"gt": "24"}}
gte größer oder gleich {"age": {"gte": "24"}}
lt Weniger als {"age": {"lt": "24"}}
lte Gleich oder kleiner als {"age": {"lte": "24"}}
mögen 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]}}
im aufzählen {"name": {"in": ["tom", "lily"]}}
nicht in aufzählen {"name": {"not_in": ["tom", "lily"]}}
oder ODER-Betrieb {"oder": [{"Name": "Tom"}, {"Alter": 24}]}

überspringen überspringen überspringen

Über die Option skip 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 Option limit können Sie die Anzahl der zurückgegebenen Datensätze begrenzen. Die gültige Anzahl der limit beträgt 1-1000 und die Standardeinstellung ist 100.

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

Reihenfolge gibt die Sortiermethode an

Verwenden Sie die order Option die Sortiermethode des zurückgegebenen Ergebnismenge gesetzt Wenn der Feldname enthält. - bevor sie es in umgekehrter Reihenfolge.

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

count gibt die Gesamtzahl der Ergebnisse zurück

Durch Erhöhen der count beim Anfordern kann die Gesamtzahl der Ergebnismengen zurückgegeben werden, 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, count und 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" } ] }

Erstellen Sie Erweiterungsobjekte

Durch Definieren von hasOne und hasMany durch orm kann die Beziehung 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); };

Erweiterte Objektzugriffs-API

Das Folgende ist die API-Definition des Erweiterungsobjekts:

URL Methode Aktion
/1.0/:className/:id/:extendName STELLEN Erweiterungsobjekt festlegen
/1.0/:className/:id/:extendName POST Erstellen Sie ein Erweiterungsobjekt
/1.0/:className/:id/:extendName/:rid BEKOMMEN Erweitertes Objekt lesen
/1.0/:className/:id/:extendName/:rid STELLEN Ändern Sie das Erweiterungsobjekt
/1.0/:className/:id/:extendName/:rid LÖSCHEN Erweiterungsobjekt löschen
/1.0/:className/:id/:extendName BEKOMMEN Fragen Sie die Liste der erweiterten Objekte ab

Erweiterungsobjekt festlegen

Durch Festlegen eines erweiterten Objekts wird eine Verbindung zwischen zwei unabhängigen Objekten hergestellt. Zum Beispiel hat Tom ein Haustier namens Katze adoptiert, was mit den 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

Im Aufruf muss die ID der Katze im Körper angegeben werden.

Erstellen Sie ein Erweiterungsobjekt

Durch direktes Erstellen erweiterter Objekte können Sie beim Erstellen von Objekten Verbindungen zwischen Objekten herstellen. sowie:

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 eine Assoziationsbeziehung mit Tom wird hergestellt.

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

Ändern Sie das Erweiterungsobjekt

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

Erweiterungsobjekt löschen

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

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 bedingte Filterung:

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

ACL

Sie können Datenberechtigungen steuern, indem Sie Modell-ACLs definieren. sowie:

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 Thema Beschreibungen, Benutzer - id , Benutzer role und * . id zeigt an einen bestimmten Benutzer, role einen Benutzer mit einer bestimmten Rolle zeigt, und * zeigt alle Benutzer:

Hauptkörper Beschreibung Priorität
Ich würde Spezifische Benutzer-ID 1
Rolle Benutzergruppenname 2
* * Alles 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.

Die obige Berechtigungskonfiguration gibt beispielsweise an, dass die user lesen kann, Benutzer 57fbbdb0a2400000 verfügt über alle Berechtigungen, während andere Benutzer keine Berechtigungen haben.

Behörde

ACL kategorisiert fünf Arten von Berechtigungen basierend auf dem API-Verhalten:

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

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

Wenn Sie im obigen Beispiel beispielsweise festlegen müssen, dass der user nur den title und die detail lesen darf und andere Personen den title lesen können, können Sie ihn wie user 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 für die gesamte Klasse werden für das Modell festgelegt. Wenn Sie Berechtigungen für bestimmte Objekte festlegen müssen, können Sie OACL festlegen, um Folgendes zu erreichen:

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 sind alle Besuche verboten. Die Berechtigungen werden gemäß den folgenden Schritten überprüft:

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

Erweiterte Objektberechtigungen

Die Zugriffsberechtigungssteuerung des erweiterten Objekts ähnelt der des Basisobjekts. Der einzige Unterschied besteht darin, dass sie in der 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 überprüfen und seine pets frei überprüfen und durchsuchen. Der Benutzer selbst kann alle seine eigenen Daten manipulieren und hat alle Rechte an seinen Haustierinformationen.

Bei der Überprüfung der Zugriffsberechtigung des erweiterten Objekts werden die Objektberechtigung und die erweiterte Objektberechtigung getrennt geprüft. Zum Beispiel die folgende Anfrage:

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

Die Berechtigungen werden gemäß den folgenden Schritten überprü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. Bei komplexen Datenoperationen kann dies durch Anpassen der Funktion abgeschlossen werden.

Die überwiegende Mehrheit der Berechtigungen kann von ACL gesteuert werden, und es ist keine Funktion erforderlich, 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 der Datendefinition abgeschlossen haben , können Sie verwenden app.diagram() , svg app.diagram() das zu Zeichnen svg - Format Klassendiagramm des Datenmodells, und es in der Datei speichern ein Bild ähnlich dem folgenden zu erhalten: Diagramm