fib-app
framework API di base dell'applicazione fibjs
Installare
1npm install fib-app [--save]
Test
1npm test
Crea uno 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();
Dov'è person
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 ed è possibile utilizzare anche altre funzioni ORM, come controllo del tipo, eventi, ecc.
Formato dati API
Per le richieste POST e PUT, il corpo della richiesta deve essere in formato JSON e il Content-Type 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.
Se una richiesta ha avuto esito positivo o meno è indicato dal codice di stato HTTP. Un codice di stato 2XX indica successo, mentre un codice di stato 4XX indica che la richiesta non è riuscita. Quando una richiesta fallisce, il corpo della risposta è ancora un oggetto JSON, ma contiene sempre il codice e i campi del messaggio, che puoi utilizzare per il debug. Ad esempio, se una richiesta di autenticazione dell'autorizzazione non riesce, 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 è diviso in tre parti: le prime tre cifre 403 rappresentano il tipo di errore, 05 rappresenta il numero della scheda tecnica e 01 rappresenta il codice di errore dettagliato.
Per le richieste GET vengono generalmente restituiti i dati dell'oggetto. 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
}
]
campi speciali
Nei dati dell'oggetto ci sono quattro campi con significati speciali che non possono essere modificati tramite l'API. id
Sono , updatedAt
, createdAt
, rispettivamente createdBy
.
Tra questi id
, updatedAt
i createdAt
singoli campi verranno automaticamente creati e modificati. createdBy
È necessario 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 API REST:
URL | metodo | azione |
---|---|---|
/1.0/:nomeclasse | INVIARE | Crea nuovo oggetto |
/1.0/:nomeclasse/:id | OTTENERE | Leggi oggetto |
/1.0/:nomeclasse/:id | METTERE | Modifica oggetto |
/1.0/:nomeclasse/:id | ELIMINARE | Elimina oggetto |
/1.0/:nomeclasse | OTTENERE | Interrogare l'elenco degli oggetti |
Crea nuovo oggetto
Per creare un nuovo oggetto, è necessario inviare una richiesta POST all'URL della classe, che dovrebbe includere l'oggetto stesso. Ad esempio, per creare l'oggetto mostrato sopra:
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 contenente objectId e createAt timestamp del nuovo oggetto:
1
2
3
4{
"createdAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
}
Leggi oggetto
Quando crei un oggetto, puoi recuperarne il contenuto inviando una richiesta GET alla posizione nell'intestazione restituita. 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 createdAt
e :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 restituito keys
, puoi personalizzare il contenuto restituito, keys
ovvero una ,
stringa di nomi di campo separati da:
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 esistenti di un oggetto, puoi inviare una richiesta PUT all'URL corrispondente dell'oggetto. Eventuali chiavi non specificate non verranno modificate, 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
campi id
che indicano quando si è verificato l'aggiornamento:
1
2
3
4{
"updatedAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
}
Elimina oggetto
Per eliminare un oggetto, puoi inviare una richiesta DELETE all'URL dell'oggetto specificato, ad esempio:
1curl -X DELETE http://localhost/1.0/person/57fbbdb0a2400000
Interrogare l'elenco degli oggetti
Puoi ottenere più oggetti contemporaneamente inviando una richiesta GET all'URL della classe, senza parametri URL. Ecco come ottenere semplicemente tutti gli utenti:
1curl -X GET http://localhost/1.0/person
Il valore restituito è un oggetto JSON contenente il campo dei 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 del campo chiavi
Come per la query sugli oggetti, è possibile keys
personalizzare i campi inclusi nei risultati restituiti impostandoli quando si esegue la query sull'elenco. keys
Il contenuto è una ,
stringa di nomi di campo separati da , ad esempio:
1curl -X GET http://localhost/1.0/person?keys=name%2Cage
Verrà specificato che verranno restituiti solo i campi name
e .age
dove condizione del filtro
where
L'oggetto della query può essere vincolato sotto forma di parametri.
where
Il valore del parametro deve essere codificato JSON. Cioè, se guardi la richiesta URL effettiva effettuata, dovrebbe essere prima codificata in JSON e poi codificata in URL. Il where
modo più semplice per utilizzare i parametri è includere la chiave e il valore appropriati. Ad esempio, se volessimo cercare gli utenti di nome Tom, costruiremmo la query in questo modo:
1curl -X GET http://localhost/1.0/person?where=%7B%22name%22%3A%22tom%22%7D
where
Il valore è una stringa JSON codificata in urlen, il contenuto è:{"name":"tom"}
Oltre a far corrispondere esattamente un determinato valore, where
sono supportati anche metodi di confronto come l'inclusione. where
I parametri supportano le seguenti opzioni:
chiave | operazione | campione |
---|---|---|
eq | pari | {"nome":{"eq":"tom"}} o {"nome":"tom"} |
ne | non uguale a | {"nome":{"ne":"tom"}} |
gt | più del | {"età":{"gt":"24"}} |
gte | maggiore o uguale a | {"età":{"gte":"24"}} |
lt | meno di | {"età":{"lt":"24"}} |
lte | minore o uguale a | {"età":{"lte":"24"}} |
Piace | domanda confusa | {"nome":{"mi piace":"%m"}} |
non come | domanda confusa | {"name":{"not_like":"%m"}} |
fra | Confronto di intervalli | {"età":{"tra":[22,25]}} |
non in mezzo | Confronto di intervalli | {"età":{"non_tra":[22,25]}} |
In | enumerare | {"name":{"in":["tom","lily"]}} |
Non in | enumerare | {"name":{"not_in":["tom","lily"]}} |
O | Operazione OR | {"o":[{"nome":"tom"},{"età":24}]} |
salta salta record
Tramite skip
l'opzione è possibile saltare il numero specificato di record per ottenere l'effetto di girare pagina.
1curl -X GET http://localhost/1.0/person?skip=100
limit restituisce il limite del record
Tramite limit
l'opzione è possibile limitare il numero di record restituiti. limit
I numeri validi sono 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. Quando il nome del campo lo precede, -
è in ordine inverso.
1curl -X GET http://localhost/1.0/person?order=-id
count restituisce il numero totale di risultati
Incrementato su richiesta count
Il numero totale di set di risultati che possono essere restituiti durante la restituzione del contenuto specificato.
1curl -X GET http://localhost/1.0/person?count=1&limit=1
In questo momento, il risultato restituito conterrà due campi: count
e results
, contenenti rispettivamente il numero 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"
}
]
}
Crea oggetto estensione
Definendo hasOne e hasMany tramite ORM è possibile definire l'associazione tra oggetti e rifletterla sulle 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
Quella che segue è la definizione API dell'oggetto estensione:
URL | metodo | azione |
---|---|---|
/1.0/:nomeclasse/:id/:nomeestensione | METTERE | Imposta oggetto estensione |
/1.0/:nomeclasse/:id/:nomeestensione | INVIARE | Crea oggetto estensione |
/1.0/:nomeclasse/:id/:nomeestensione/:rid | OTTENERE | Leggi oggetto estensione |
/1.0/:nomeclasse/:id/:nomeestensione/:rid | METTERE | Modifica oggetto estensione |
/1.0/:nomeclasse/:id/:nomeestensione/:rid | ELIMINARE | Elimina oggetto esteso |
/1.0/:nomeclasse/:id/:nomeestensione | OTTENERE | Interroga l'elenco degli oggetti esteso |
Imposta oggetto estensione
Impostare un oggetto estensione significa stabilire una relazione tra due oggetti indipendenti. Ad esempio, se Tom adotta un animale domestico chiamato gatto, può utilizzare le seguenti operazioni per raggiungere questo obiettivo:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"id": "57fbbdb0a2400007"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets
Nella chiamata, l'ID del gatto deve essere specificato nel corpo.
Crea oggetto estensione
La creazione diretta di oggetti estesi può 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.
Leggi oggetto estensione
La lettura degli oggetti estesi è molto simile alla lettura degli oggetti base e supporta anche l'opzione chiavi:
1curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Modifica oggetto estensione
La lettura degli oggetti estesi è molto simile alla lettura degli oggetti base:
1
2
3
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"name": "cat 1"}' \
http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
Elimina oggetto esteso
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
Interroga l'elenco degli oggetti esteso
L'esecuzione di query sull'elenco di oggetti esteso è molto simile all'esecuzione di query sull'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 specificata alcuna 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 utenti | 2 |
* | Tutto | 3 |
Quando si controllano le autorizzazioni, corrisponderà prima id
alle autorizzazioni corrispondenti. Se non specificato, corrisponderà role
alle autorizzazioni corrispondenti dell'utente. Se è ancora specificato, verificare se *
sono specificate le autorizzazioni di. Se *
non specificato, non esiste alcuna autorizzazione.
Ad esempio, nella configurazione dei permessi di cui sopra, user
il gruppo di utenti viene specificato per essere in grado di leggere. L'utente 57fbbdb0a2400000
dispone di tutti i permessi, ma gli altri utenti non dispongono di alcun permesso.
Autorizzazioni
ACL classifica le autorizzazioni in cinque categorie in base al comportamento dell'API:
Autorizzazioni | descrivere | tipologie consentite |
---|---|---|
creare | Crea oggetto | vero/falso/array |
Leggere | Leggi oggetto | vero/falso/array |
scrivere | Modifica oggetto | vero/falso/array |
eliminare | Elimina oggetto | vero falso |
Trovare | Interrogare l'elenco degli oggetti | vero falso |
* | Corrisponde a tutte le autorizzazioni | vero/falso/array |
Le autorizzazioni vengono impostate true
per consentire l'accesso, false
negare l'accesso e array
consentire solo l'accesso ai campi specificati. delete
e find
non sono accettati e vengono trattati allo stesso modo array
se impostati . Se l'autorizzazione specificata non esiste, verranno abbinate le autorizzazioni con lo stesso oggetto. Se nessuno dei due esiste, interroga nuovamente l'oggetto del livello di priorità successivo.array
true
*
Ad esempio, nell'esempio sopra, se devi impostare user
only read title
e detail
consentire ad altri di 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']
}
}
}
Autorizzazioni oggetto
I permessi impostati sul Modello sono i permessi dell'intera classe. Se hai bisogno di impostare permessi su oggetti specifici, puoi farlo impostando OACL:
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à interdetto. Le autorizzazioni vengono controllate come segue:
person[57fbbdb0a2400000]
=>OACL
person
=>ACL
Autorizzazioni estese sugli oggetti
Il controllo dei permessi di accesso degli oggetti estesi è simile ai permessi degli oggetti base, l'unica differenza è che l'ACL deve essere specificata 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 l' name
insieme delle informazioni personali sex
, controllarle e ricercarle liberamente pets
, l'utente stesso può gestire tutti i propri dati e avere piena autorizzazione per le informazioni sul proprio animale domestico.
Quando si controllano le autorizzazioni di accesso per gli oggetti estesi, le autorizzazioni degli oggetti e le autorizzazioni degli oggetti estesi 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
È possibile definire API per il modello e operazioni complesse sui dati possono essere completate tramite funzioni personalizzate.
La maggior parte delle autorizzazioni può essere controllata tramite ACL e non è necessario implementare le autorizzazioni basate su oggetti tramite Function. La funzione può essere utilizzata per completare autorizzazioni basate sui dati, ad esempio concedere autorizzazioni a diversi gruppi di utenti in base allo stato di approvazione. E molteplici modifiche, come la necessità di modificare più record di database.
Disegna il modello dei dati
Dopo aver completato la definizione dei dati, puoi utilizzare per app.diagram()
disegnare il diagramma delle classi del formato del modello dati svg
. Quando salvi in un file, otterrai un'immagine simile alla seguente: