Fantastico modulo comunitario

fib-app

framework API di base dell'applicazione fibjs

Installare

1
npm install fib-app [--save]

Test

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

Dov'è personil 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 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 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 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. idSono , updatedAt, createdAt, rispettivamente createdBy.

Tra questi id, updatedAti createdAtsingoli 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 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 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:

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

Il corpo restituito è un oggetto JSON contenente tutti i campi forniti dall'utente più i campi createdAte :updatedAtid

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, keysovvero una ,stringa di nomi di campo separati da:

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 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 4
curl -X PUT \ -H "Content-Type: application/json" \ -d '{"age": 25}' \ http://localhost/1.0/person/57fbbdb0a2400000

L'oggetto JSON restituito conterrà updatedAtcampi idche 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:

1
curl -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:

1
curl -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 keyspersonalizzare i campi inclusi nei risultati restituiti impostandoli quando si esegue la query sull'elenco. keysIl contenuto è una ,stringa di nomi di campo separati da , ad esempio:

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

Verrà specificato che verranno restituiti solo i campi namee .age

dove condizione del filtro

whereL'oggetto della query può essere vincolato sotto forma di parametri.

whereIl 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 wheremodo 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:

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

whereIl valore è una stringa JSON codificata in urlen, il contenuto è:{"name":"tom"}

Oltre a far corrispondere esattamente un determinato valore, wheresono supportati anche metodi di confronto come l'inclusione. whereI 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 skipl'opzione è possibile saltare il numero specificato di record per ottenere l'effetto di girare pagina.

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

limit restituisce il limite del record

Tramite limitl'opzione è possibile limitare il numero di record restituiti. limitI numeri validi sono 1-1000 e il valore predefinito è 100.

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

order specifica il metodo di ordinamento

Utilizzare orderl'opzione per impostare il metodo di ordinamento del set di risultati restituito. Quando il nome del campo lo precede, -è in ordine inverso.

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

count restituisce il numero totale di risultati

Incrementato su richiesta countIl numero totale di set di risultati che possono essere restituiti durante la restituzione del contenuto specificato.

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

In questo momento, il risultato restituito conterrà due campi: counte 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 9
module.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 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 può stabilire connessioni tra oggetti durante la creazione di oggetti. Per esempio:

1 2 3 4
curl -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:

1
curl -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 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, dissolve solo la relazione tra gli oggetti:

1
curl -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:

1
curl -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 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 } } }; } }); };

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 rolee *, idche rappresentano un utente specifico, rolerappresentano 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 idalle autorizzazioni corrispondenti. Se non specificato, corrisponderà rolealle 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, useril gruppo di utenti viene specificato per essere in grado di leggere. L'utente 57fbbdb0a2400000dispone 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 trueper consentire l'accesso, falsenegare l'accesso e arrayconsentire solo l'accesso ai campi specificati. deletee findnon sono accettati e vengono trattati allo stesso modo arrayse 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.arraytrue*

Ad esempio, nell'esempio sopra, se devi impostare useronly read titlee detailconsentire 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 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 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 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 l' nameinsieme 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:

1
curl -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: diagramma