fib-app
framework API di base dell'applicazione fibjs
installare
1npm install fib-app [--save]
test
1npm test
costruire lo script di base
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();
Tra questi person
c'è il modulo di definizione del modello, il contenuto è il seguente:
1
2
3
4
5
6
7module.exports = db => {
db.define('person', {
name: String,
sex: ["male", "female"],
age: Number
});
};
Questa è una definizione orm standard e puoi anche utilizzare altre funzioni orm, come il controllo del tipo, gli eventi, ecc.
Formato dei dati dell'API
Per le richieste POST e PUT, il corpo della richiesta deve essere in formato JSON e il tipo di contenuto dell'intestazione HTTP deve essere impostato su application/json.
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"name": "tom","sex":"male","age":23}' \
http://localhost/1.0/person/57fbbdb0a2400000
Per tutte le richieste, il formato della risposta è un oggetto JSON.
Il successo di una richiesta è indicato dal codice di stato HTTP. Un codice di stato 2XX indica il successo, mentre un 4XX indica che la richiesta non è riuscita. Quando una richiesta fallisce, il corpo della risposta è ancora un oggetto JSON, ma contiene sempre due campi, codice e messaggio, che puoi utilizzare per il debug. Ad esempio, se una richiesta di autorizzazione fallisce, verranno restituite le seguenti informazioni:
1
2
3
4{
"code": 4030501,
"message": "The operation isn’t allowed for clients due to class-level permissions."
}
Il codice del codice è diviso in tre parti, le prime tre cifre 403 rappresentano il tipo di errore, 05 rappresenta il numero della tabella dati e 01 rappresenta il codice di errore dettagliato.
Per una richiesta GET, di solito vengono restituiti i dati dell'oggetto e, a seconda dell'indirizzo della richiesta GET, può essere restituito un oggetto o un array. Per esempio:
1
2
3
4
5{
"name": "tom",
"sex": "male",
"age": 23
}
O:
1
2
3
4
5
6
7
8
9
10
11
12[
{
"name": "tom",
"sex": "male",
"age": 23
},
{
"name": "lily",
"sex": "female",
"age": 22
}
]
campo speciale
Nei dati oggetto, ci sono quattro campi con un significato speciale, che non possono essere modificati tramite API. id
Sono , updatedAt
, createdAt
, rispettivamente createdBy
.
Tra questi id
, updatedAt
un createdAt
singolo campo viene creato e modificato automaticamente. createdBy
Devi specificare tu stesso il tipo.
API di accesso agli oggetti di base
Dopo aver completato tale definizione dei dati, avrai direttamente una serie di chiamate di interfaccia conformi alla specifica dell'API REST:
URL | metodo | azione |
---|---|---|
/1.0/:nomeclasse | INVIARE | creare un nuovo oggetto |
/1.0/:nomeclasse/:id | OTTENERE | leggere oggetto |
/1.0/:nomeclasse/:id | METTERE | modifica oggetto |
/1.0/:nomeclasse/:id | ELIMINARE | eliminare oggetto |
/1.0/:nomeclasse | OTTENERE | elenco di oggetti di query |
creare un nuovo oggetto
Per creare un nuovo oggetto, è necessario inviare una richiesta POST all'URL della classe, che dovrebbe contenere l'oggetto stesso. Ad esempio, per creare l'oggetto sopra descritto:
1
2
3
4curl -X POST \
-H "Content-Type: application/json" \
-d '{"name": "tom","sex":"male","age":23}' \
http://localhost/1.0/person
Quando la creazione ha esito positivo, il ritorno HTTP è 201 Created e il corpo della risposta è un oggetto JSON, inclusi objectId e createdAt timestamp del nuovo oggetto:
1
2
3
4{
"createdAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
}
leggere oggetto
Quando crei un oggetto, puoi recuperarne il contenuto inviando una richiesta GET all'intestazione Location return. Ad esempio, per ottenere l'oggetto che abbiamo creato sopra:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000
Il corpo restituito è un oggetto JSON contenente tutti i campi forniti dall'utente più i campi e createdAt
:updatedAt
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"
}
Impostando il campo di ritorno keys
, puoi personalizzare il contenuto restituito.Il keys
contenuto è una stringa di nomi di campo ,
separati :
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000?keys=name%2Csex
sarà di ritorno:
1
2
3
4{
"name": "tom",
"sex": "male"
}
modifica oggetto
Per modificare i dati già presenti in un oggetto, puoi inviare una richiesta PUT all'URL corrispondente dell'oggetto e qualsiasi chiave non specificata non verrà modificata, quindi puoi aggiornare solo un sottoinsieme dei dati dell'oggetto . Ad esempio, cambiamo un campo età del nostro oggetto:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"age": 25}' \
http://localhost/1.0/person/57fbbdb0a2400000
L'oggetto JSON restituito conterrà updatedAt
e id
campi che indicano quando si è verificato l'aggiornamento:
1
2
3
4{
"updatedAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
}
eliminare oggetto
Per eliminare un oggetto, invia una richiesta DELETE all'URL dell'oggetto specificato, ad esempio:
1curl -X DELETE http://localhost/1.0/person/57fbbdb0a2400000
elenco di oggetti di query
Puoi recuperare più oggetti contemporaneamente inviando una richiesta GET all'URL della classe senza alcun parametro URL. Ecco un modo semplice per ottenere tutti gli utenti:
1curl -X GET http://localhost/1.0/person
Il valore restituito è un oggetto JSON contenente il campo risultati, il cui valore è un elenco di oggetti:
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"
}
]
personalizzazione campo chiavi
Analogamente alla query dell'oggetto, è possibile personalizzare i campi inclusi nel risultato restituito keys
impostando . keys
Il contenuto di è una stringa del nome di campo ,
separata , ad esempio:
1curl -X GET http://localhost/1.0/person?keys=name%2Cage
specificherà name
che age
verranno restituiti solo i campi e .
dove condizione di filtro
L'oggetto query può essere vincolato sotto forma di where
parametri .
where
Il valore del parametro deve essere codificato in JSON. Detto questo, se osservi l'effettiva richiesta di URL effettuata, dovrebbe essere codificata in JSON e quindi codificata in URL. Il modo più semplice per utilizzare where
i parametri consiste nell'includere la chiave e il valore come previsto. Ad esempio, se vogliamo cercare utenti con il nome tom, dovremmo costruire la query in questo modo:
1curl -X GET http://localhost/1.0/person?where=%7B%22name%22%3A%22tom%22%7D
where
Il valore di è una stringa JSON dopo urlencode, il contenuto è:{"name":"tom"}
Oltre a far corrispondere esattamente un dato valore, where
supporta anche metodi di confronto, come contains. where
Il parametro supporta le seguenti opzioni:
chiave | operazione | campione |
---|---|---|
eq | pari | {"name":{"eq":"tom"}} o {"name":"tom"} |
no | non uguale a | {"name":{"ne":"tom"}} |
gt | più del | {"age":{"gt":"24"}} |
gte | maggiore o uguale a | {"age":{"gte":"24"}} |
lt | meno di | {"age":{"lt":"24"}} |
LTE | minore o uguale a | {"age":{"lte":"24"}} |
Piace | interrogazione sfocata | {"name":{"mi piace":"%m"}} |
non come | interrogazione sfocata | {"name":{"not_like":"%m"}} |
fra | Confronto tra intervalli | {"età":{"tra":[22,25]}} |
non in mezzo | Confronto tra intervalli | {"età":{"non_tra":[22,25]}} |
In | enumerare | {"name":{"in":["tom","lily"]}} |
Non in | enumerare | {"name":{"not_in":["tom","lily"]}} |
O | Operazione OR | {"or":[{"name":"tom"},{"età":24}]} |
salta salta la registrazione
Attraverso skip
l'opzione , puoi saltare il numero specificato di record per ottenere l'effetto di girare le pagine.
1curl -X GET http://localhost/1.0/person?skip=100
limit restituisce limite di record
Tramite limit
l'opzione , puoi limitare il numero limit
di record restituiti, il numero effettivo è 1-1000 e il valore predefinito è 100.
1curl -X GET http://localhost/1.0/person?limit=100
order specifica il metodo di ordinamento
Utilizzare order
l'opzione per impostare il metodo di ordinamento del set di risultati restituito e il nome del campo contiene -
in ordine inverso.
1curl -X GET http://localhost/1.0/person?order=-id
count restituisce il numero totale di risultati
Incremento su richiesta Il numero totale di set di risultati count
che possono essere restituiti durante la restituzione del contenuto specificato.
1curl -X GET http://localhost/1.0/person?count=1&limit=1
A questo punto, il risultato restituito conterrà count
e results
due campi, che contengono rispettivamente il totale e il risultato:
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"
}
]
}
creare un oggetto di estensione
Definendo hasOne e hasMany tramite orm, puoi definire la relazione tra gli oggetti e rifletterla sull'API, ad esempio:
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);
};
API di accesso esteso agli oggetti
Quanto segue è la definizione API per l'oggetto di estensione:
URL | metodo | azione |
---|---|---|
/1.0/:className/:id/:extendName | METTERE | imposta l'oggetto di estensione |
/1.0/:className/:id/:extendName | INVIARE | Crea oggetto di estensione |
/1.0/:className/:id/:extendName/:rid | OTTENERE | leggere l'oggetto di estensione |
/1.0/:className/:id/:extendName/:rid | METTERE | modificare l'oggetto di estensione |
/1.0/:className/:id/:extendName/:rid | ELIMINARE | eliminare l'oggetto di estensione |
/1.0/:className/:id/:extendName | OTTENERE | Interrogare l'elenco degli oggetti estesi |
imposta l'oggetto di estensione
Impostare un oggetto esteso significa stabilire una connessione tra due oggetti indipendenti. Ad esempio, Tom adotta un animale domestico di nome gatto, che può essere realizzato con le seguenti operazioni:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"id": "57fbbdb0a2400007"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets
Nella chiamata, è necessario specificare l'id del gatto nel corpo.
Crea oggetto di estensione
Crea direttamente oggetti estesi, puoi stabilire connessioni tra oggetti durante la creazione di oggetti. Per esempio:
1
2
3
4curl -X POST \
-H "Content-Type: application/json" \
-d '{"name": "cat"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets
Verrà creato un animale domestico chiamato gatto e associato a Tom.
leggere l'oggetto di estensione
La lettura di oggetti di estensione è molto simile alla lettura di oggetti di base e supporta anche l'opzione keys:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
modificare l'oggetto di estensione
La lettura di un oggetto di estensione è molto simile alla lettura di un oggetto di base:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"name": "cat 1"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
eliminare l'oggetto di estensione
L'eliminazione di un oggetto esteso non elimina l'oggetto stesso, dissolve solo la relazione tra gli oggetti:
1curl -X DETELE http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Interrogare l'elenco degli oggetti estesi
L'interrogazione dell'elenco di oggetti estesi è molto simile all'interrogazione dell'elenco di oggetti di base e supporta anche opzioni come chiavi e filtri condizionali:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets
ACL
Le autorizzazioni per i dati possono essere controllate definendo l'ACL del modello. Per esempio:
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
}
}
};
}
});
};
Se non viene specificato alcun ACL durante la definizione del modello, equivale a impostare le autorizzazioni predefinite:
1
2
3
4
5{
"*": {
"*": true
}
}
corpo principale
Esistono tre tipi di descrizioni dell'oggetto ACL, utente id
, utente role
e *
, id
che rappresentano un utente specifico, role
rappresentano gli utenti con un determinato ruolo e *
rappresentano tutti gli utenti:
corpo principale | descrivere | priorità |
---|---|---|
id | ID utente specifico | 1 |
ruolo | nome del gruppo di utenti | 2 |
* | Tutto | 3 |
Durante il controllo delle autorizzazioni, corrisponderà prima alle autorizzazioni id
corrispondenti . Se non specificato, corrisponde role
alle autorizzazioni corrispondenti dell'utente. Se è ancora specificato, controlla se sono specificate le autorizzazioni *
di . Se *
non è specificato, non esiste alcuna autorizzazione.
Ad esempio, nella configurazione delle autorizzazioni di cui sopra, il gruppo user
di utenti può leggere, l'utente 57fbbdb0a2400000
dispone di tutte le autorizzazioni e gli altri utenti non dispongono di autorizzazioni.
autorizzazioni
ACL classifica le autorizzazioni in cinque tipi in base al comportamento dell'API:
autorizzazioni | descrivere | tipo consentito |
---|---|---|
creare | creare oggetto | vero/falso/matrice |
Leggere | leggere oggetto | vero/falso/matrice |
scrivere | modifica oggetto | vero/falso/matrice |
eliminare | eliminare oggetto | vero falso |
Trovare | elenco di oggetti di query | vero falso |
* | corrispondono a tutte le autorizzazioni | vero/falso/matrice |
Le autorizzazioni sono impostate true
per consentire l'accesso, false
per vietare l'accesso e array
per consentire l'accesso solo ai campi specificati. delete
e find
non sono accettati array
e vengono trattati array
come true
. Se l'autorizzazione specificata non esiste, abbina *
l'autorizzazione . Se non ne esistono, interroga nuovamente l'oggetto della priorità successiva.
Ad esempio, nell'esempio precedente, se devi impostare Consenti user
solo la lettura title
e detail
gli altri possono leggere title
, puoi impostarlo in questo modo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"*": {
"*": false,
"read": ['title']
},
"57fbbdb0a2400000": {
"*": true
},
"roles": {
"user": {
"read": ['title', 'detail']
}
}
}
permessi oggetto
Ciò che è impostato sul modello è l'autorità dell'intera classe.Se è necessario impostare l'autorità per un oggetto specifico, è possibile impostare l'OACL per ottenerlo:
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;
}
});
};
In questo esempio, quando il visitatore è l'oggetto stesso, tutte le operazioni saranno consentite, altrimenti ogni accesso sarà proibito. Le autorizzazioni vengono controllate come segue:
person[57fbbdb0a2400000]
=>OACL
person
=>ACL
Autorizzazioni oggetto estese
Il controllo di accesso degli oggetti estesi è simile a quello degli oggetti di base, l'unica differenza è che l'ACL deve essere specificato separatamente:
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 questa definizione, chiunque può controllare le informazioni personali name
e sex
, e controllare e cercare liberamente le proprie pets
, l'utente stesso può gestire tutti i propri dati e avere piena autorità sulle informazioni del proprio animale domestico.
Quando si controllano le autorizzazioni di accesso sugli oggetti estesi, le autorizzazioni oggetto e le autorizzazioni oggetto esteso vengono controllate separatamente. Ad esempio, la seguente richiesta:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Le autorizzazioni vengono controllate come segue:
pets[57fbbdb0a2400007]
=>OACL
person[57fbbdb0a2400000]
=>OACL
=>extends
=>pets
person
=>ACL
=>extends
=>pets
pets
=>ACL
funzione
L'API può essere definita per il modello e le operazioni complesse sui dati possono essere eseguite personalizzando la funzione.
La maggior parte delle autorizzazioni può essere controllata tramite ACL e le autorizzazioni basate sugli oggetti non devono essere implementate tramite Function. La funzione può essere utilizzata per completare autorizzazioni basate sui dati, come la concessione di autorizzazioni a diversi gruppi di utenti in base allo stato di approvazione. E più modifiche, come la necessità di modificare più record del database.
Disegna il modello dati
Dopo aver completato la definizione dei dati, è possibile utilizzare per app.diagram()
disegnare svg
il diagramma delle classi di formato del modello di dati e salvarlo in un file per ottenere un'immagine simile alla seguente: