fib-app
Grundlegendes API-Framework für die fibjs-Anwendung
Installieren
1npm install fib-app [--save]
Prüfen
1npm 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
21const 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 person
ist das Modelldefinitionsmodul, der Inhalt ist wie folgt:
1
2
3
4
5
6
7module.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
4curl -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. .createdAt
createdBy
Darunter werden einzelne Felder automatisch erstellt und geändert id
. Sie müssen den Typ selbst angeben.updatedAt
createdAt
createdBy
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
4curl -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:
1curl -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
, updatedAt
und 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 keys
können Sie den zurückgegebenen Inhalt anpassen, keys
bei dem es sich um eine ,
Zeichenfolge von Feldnamen handelt, die durch Folgendes getrennt sind:
1curl -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
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"age": 25}' \
http://localhost/1.0/person/57fbbdb0a2400000
Das zurückgegebene JSON-Objekt enthält updatedAt
und id
Felder, 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:
1curl -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:
1curl -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 keys
die in den zurückgegebenen Ergebnissen enthaltenen Felder anpassen, indem Sie sie beim Abfragen der Liste festlegen. keys
Der Inhalt ist eine ,
Zeichenfolge von Feldnamen, die durch getrennt sind, zum Beispiel:
1curl -X GET http://localhost/1.0/person?keys=name%2Cage
Gibt an, dass nur die Felder „ name
und“ age
zurückgegeben werden.
wo Filterbedingung
where
Das Abfrageobjekt kann in Form von Parametern eingeschränkt werden.
where
Der 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 where
Mö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:
1curl -X GET http://localhost/1.0/person?where=%7B%22name%22%3A%22tom%22%7D
where
Der Wert ist eine URL-kodierte JSON-Zeichenfolge, der Inhalt ist:{"name":"tom"}
Neben der genauen Übereinstimmung mit einem bestimmten Wert where
werden auch Vergleichsmethoden wie die Einbeziehung unterstützt. where
Parameter 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 skip
dieser Option können Sie die angegebene Anzahl von Datensätzen überspringen, um den Effekt des Umblätterns zu erzielen.
1curl -X GET http://localhost/1.0/person?skip=100
limit gibt Datensatzlimit zurück
Mit limit
dieser Option können Sie die Anzahl der zurückgegebenen Datensätze begrenzen. limit
Die gültigen Zahlen sind 1-1000 und der Standardwert ist 100.
1curl -X GET http://localhost/1.0/person?limit=100
order gibt die Sortiermethode an
Verwenden Sie order
die Option, um die Sortiermethode des zurückgegebenen Ergebnissatzes festzulegen. Wenn der Feldname davor steht, -
ist die Reihenfolge umgekehrt.
1curl -X GET http://localhost/1.0/person?order=-id
count gibt die Gesamtzahl der Ergebnisse zurück
Auf Anfrage erhöht. count
Die Gesamtzahl der Ergebnismengen, die zurückgegeben werden können, während der angegebene Inhalt zurückgegeben wird.
1curl -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"
}
]
}
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
9module.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
4curl -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
4curl -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:
1curl -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
4curl -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:
1curl -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:
1curl -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
25const 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 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 role
und *
, id
die einen bestimmten Benutzer, role
Benutzer 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 id
den entsprechenden Berechtigungen abgeglichen. Wenn nicht angegeben, dann mit role
den 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 user
angegeben, dass die Benutzergruppe lesen darf. Der Benutzer 57fbbdb0a2400000
hat 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, false
den Zugriff verweigern und array
nur den Zugriff auf bestimmte Felder erlauben. delete
und find
werden nicht akzeptiert und gleich behandelt, array
wenn 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.array
true
*
Wenn Sie beispielsweise im obigen Beispiel „ user
Nur Lesen“ festlegen title
und detail
anderen 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
24module.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
41module.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 name
Summe der persönlichen Informationen überprüfen sex
und 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:
1curl -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: