Fantastico modulo comunitario

FIB-app

Quadro API di base per l'applicazione fibjs

Installare

1
npm install fib-app [--save]

Test

1
npm test

Stabilire lo script di base

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

Dove person è il modulo di definizione del modello, il contenuto è il seguente:

1 2 3 4 5 6 7
module.exports = db => { db.define('person', { name: String, sex: ["male", "female"], age: Number }); };

Questa è una definizione orm standard e può anche utilizzare altre funzioni di orm, come il controllo del tipo, gli eventi, ecc.

Formato dati 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 4
curl -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 di risposta è un oggetto JSON.

Il successo di una richiesta è indicato dal codice di stato HTTP. Un codice di stato 2XX indica un esito positivo e un 4XX indica un errore della richiesta. Quando una richiesta fallisce, il corpo della risposta è ancora un oggetto JSON, ma contiene sempre due campi, codice e messaggio, che è possibile utilizzare per il debug. Ad esempio, se una richiesta di 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 indicano il tipo di errore, 05 indica il numero della tabella di dati e 01 indica il codice di errore dettagliato.

Per le richieste GET, in genere vengono restituiti i dati degli oggetti, a seconda dell'indirizzo della richiesta GET, può essere restituito un oggetto o un array. ad 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

Esistono quattro campi con significati speciali nei dati oggetto, che non possono essere modificati tramite l'API. Sono id , updatedAt , createdAt , createdBy .

L' id , updatedAt , createdAt singoli campi verrà creato e modificato automaticamente. createdBy deve specificare il proprio tipo.

API di accesso agli oggetti di base

Dopo aver completato tale definizione dei dati, disponiamo direttamente di una serie di chiamate di interfaccia conformi alla specifica API REST:

url metodo azione
/1.0/:className INVIARE Crea nuovo oggetto
/1.0/:className/:id OTTENERE Leggi oggetto
/1.0/:className/:id METTERE Modifica oggetto
/1.0/:className/:id ELIMINA Elimina oggetto
/1.0/:className OTTENERE Elenco oggetti query

Crea 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 4
curl -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 Creato e il corpo della risposta è un oggetto JSON che contiene objectId e CreatedAtest tim del nuovo oggetto:

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

Leggi oggetto

Quando si crea un oggetto, è possibile ottenere il suo contenuto inviando una richiesta GET alla posizione dell'intestazione restituita. Ad esempio, per ottenere l'oggetto che abbiamo creato sopra:

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

Il corpo restituito è un oggetto JSON contenente tutti i campi forniti dall'utente oltre ai campi createdAt , updatedAt e 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 restituisce keys , è possibile restituire contenuto personalizzato, keys di un contenuto , stringhe di nomi dei campi di segmentazione:

1
curl -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. Qualsiasi chiave che non specifichi non cambierà, quindi puoi aggiornare solo un sottoinsieme dei dati dell'oggetto. Ad esempio, cambiamo un campo di età del nostro oggetto:

1 2 3 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"age": 25}' \ http://localhost/1.0/person/57fbbdb0a2400000

L'oggetto JSON restituito conterrà i campi updatedAt e id , indicando quando si è verificato l'aggiornamento:

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

Elimina oggetto

Per eliminare un oggetto, è possibile inviare una richiesta DELETE all'URL dell'oggetto specificato, ad esempio:

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

Elenco oggetti query

Puoi ottenere più oggetti contemporaneamente inviando una richiesta GET all'URL della classe senza parametri URL. Ecco un modo semplice per ottenere tutti gli utenti:

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

Il valore restituito è un oggetto JSON contenente il campo dei risultati e il suo 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 chiave

Come per la query sugli oggetti, è possibile personalizzare i campi inclusi nel risultato restituito impostando le keys durante la query dell'elenco. keys di un contenuto in , stringhe di nomi dei campi di segmentazione, ad esempio:

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

Specifica che verranno restituiti solo i due campi name ed age .

dove filtro

L'oggetto query può essere vincolato attraverso la forma dei parametri where .

Il valore del parametro where deve essere codificato JSON. Cioè, se si esamina la richiesta URL effettivamente emessa, dovrebbe essere prima codificata in JSON e quindi codificata nell'URL. Il modo più semplice per utilizzare il parametro where è includere la chiave e il valore richiesti. Ad esempio, se vogliamo cercare un utente di nome Tom, dovremmo costruire una query come questa:

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

where value è una stringa JSON dopo urlencode, il contenuto è: {"name":"tom"}

Oltre a corrispondere esattamente a un determinato valore, where supporta anche metodi di confronto, come l'inclusione. where parametro where supporta le seguenti opzioni:

chiave operazione campione
eq pari {"name": {"eq": "tom"}} o {"name": "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 Query fuzzy { "Nome": { "come": "% m"}}
non come Query fuzzy { "Nome": { "not_like": "% m"}}
fra Confronto intervalli { "Età": { "fra": [22,25]}}
non in mezzo Confronto intervalli { "Età": { "not_between": [22,25]}}
nel enumerare { "Nome": { "in": [ "tom", "lily"]}}
Non in enumerare { "Nome": { "not_in": [ "tom", "lily"]}}
o O operazione { "O": [{ "name": "tom"}, { "età": 24}]}

salta Salta i record

Tramite l'opzione skip , è possibile saltare il numero specificato di record per ottenere l'effetto di girare le pagine.

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

limit restituisce il limite del record

Tramite l'opzione limit , è possibile limitare il numero di record restituiti, il numero effettivo del limit è 1-1000, il valore predefinito è 100.

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

order specifica il metodo di ordinamento

Con l'opzione order , è possibile impostare il metodo di ordinamento del set di risultati restituito Quando il nome del campo contiene - , è in ordine inverso.

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

count restituisce il numero totale di risultati

L'aumento del count quando richiesto può restituire il numero totale di set di risultati durante la restituzione del contenuto specificato.

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

A questo punto, il risultato restituito conterrà due campi, count e results , che contengono 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 oggetti estesi

Definendo hasOne e hasMany tramite orm, la relazione tra oggetti può essere definita e riflessa nell'API, ad esempio:

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 di accesso agli oggetti estesi

Di seguito è riportata la definizione API dell'oggetto estensione:

url metodo azione
/1.0/:className/:id/:extendName METTERE Imposta oggetto esteso
/1.0/:className/:id/:extendName INVIARE Crea oggetto estensione
/1.0/:className/:id/:extendName/:rid OTTENERE Leggi oggetti estesi
/1.0/:className/:id/:extendName/:rid METTERE Modifica oggetti estesi
/1.0/:className/:id/:extendName/:rid ELIMINA Elimina oggetto esteso
/1.0/:className/:id/:extendName OTTENERE Interroga l'elenco di oggetti estesi

Imposta oggetto esteso

L'impostazione di un oggetto esteso significa stabilire una connessione tra due oggetti indipendenti. Ad esempio, Tom ha adottato un animale domestico di nome gatto, che può essere ottenuto con le seguenti operazioni:

1 2 3 4
curl -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 consente di stabilire connessioni tra oggetti durante la loro creazione. ad esempio:

1 2 3 4
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name": "cat"}' \ http://localhost/1.0/person/57fbbdb0a2400000/pets

Creerà un animale domestico di nome gatto e stabilirà un'associazione con Tom.

Leggi oggetti estesi

La lettura di oggetti estesi è simile alla lettura di oggetti base e supporta anche l'opzione keys:

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

Modifica oggetti estesi

La lettura di oggetti estesi è molto simile alla lettura di oggetti base:

1 2 3 4
curl -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, rilascia solo la relazione tra oggetti:

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

Interroga l'elenco di oggetti estesi

L'elenco oggetti estesi query è molto simile all'elenco oggetti base query e supporta anche opzioni come chiavi e filtro condizionale:

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

ACL

È possibile controllare le autorizzazioni dei dati definendo l'ACL del modello. ad 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 25
const 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 l'ACL non viene specificato durante la definizione del modello, equivale a impostare le autorizzazioni predefinite:

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

corpo principale

Esistono tre tipi di descrizioni del corpo ACL, id utente, role utente e * , id rappresenta un utente specifico, role rappresenta un utente con un determinato ruolo e * rappresenta tutti gli utenti:

corpo principale descrizione priorità
id ID utente specifico 1
ruolo Nome del gruppo utenti 2
* Tutti 3

Quando si controllano le autorizzazioni, le autorizzazioni corrispondenti id verranno confrontate per prime. Se non specificato, verranno abbinate le autorizzazioni corrispondenti al role utente. Se è ancora specificato, verificare se è stata specificata l'autorizzazione * . Se * non è specificato, non ci saranno autorizzazioni.

Ad esempio, i specifica configurazione delle autorizzazioni di cui sopra che l' user gruppo di utenti può essere letto. User 57fbbdb0a2400000 ha tutti i permessi, mentre gli altri utenti non dispongono di tutte le autorizzazioni.

Autorità

ACL classifica le autorizzazioni in cinque categorie in base al comportamento dell'API:

Autorità descrizione Tipi ammessi
creare Crea oggetto vero / falso / matrice
leggere Leggi oggetto vero / falso / matrice
Scrivi Modifica oggetto vero / falso / matrice
Elimina Elimina oggetto vero falso
trova Elenco oggetti query vero falso
* Abbina tutte le autorizzazioni vero / falso / matrice

Le autorizzazioni sono impostate su true per consentire l'accesso, false per vietare l'accesso e array per consentire l'accesso solo ai campi specificati. delete e find non accetta l' array , se l' array è impostato, viene considerato true . Se l'autorizzazione specificata non esiste, corrisponde all'autorizzazione * sotto lo stesso soggetto. Se non esiste, interroga nuovamente l'oggetto della priorità successiva.

Ad esempio, nell'esempio sopra, se è necessario impostare l' user consentire solo la lettura del title e dei detail e altri possono leggere il title , è possibile 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 dell'oggetto

Le autorizzazioni dell'intera classe sono impostate sul Modello. Se è necessario impostare autorizzazioni su oggetti specifici, è possibile impostare OACL per ottenere:

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 questo esempio, quando il visitatore è l'oggetto, saranno consentite tutte le operazioni, altrimenti sarà proibito qualsiasi accesso. Le autorizzazioni verranno controllate in base ai seguenti passaggi:

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

Autorizzazioni oggetti estese

Il controllo dei diritti di accesso degli oggetti estesi è simile ai diritti degli oggetti di base, tranne per il fatto 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 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 questa definizione, chiunque può controllare il name e il sex informazioni personali e cercare e cercare liberamente i propri pets può gestire tutti i propri dati e avere tutti i diritti per possedere le proprie informazioni sugli animali domestici.

Quando si controllano i diritti di accesso degli oggetti estesi, i diritti degli oggetti e i diritti degli oggetti estesi vengono controllati separatamente. Ad esempio, la seguente richiesta:

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

Le autorizzazioni verranno controllate in base ai seguenti passaggi:

  • pets[57fbbdb0a2400007] => OACL
  • person[57fbbdb0a2400000] => OACL => extends => pets
  • person => ACL => extends => pets
  • pets => ACL

Funzione

L'API può essere definita per il Modello, per operazioni su dati complessi, può essere completata dalla Funzione personalizzata.

La maggior parte delle autorizzazioni può essere completata tramite il controllo ACL, senza la necessità di completare le autorizzazioni basate sugli oggetti tramite la funzione. 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 di database.

Traccia il modello dati

Dopo aver completato la definizione dei dati, è possibile utilizzare app.diagram() disegnare il diagramma di classe del formato svg del modello di dati e salvarlo in un file per ottenere un'immagine simile alla seguente: diagramma