Fantastico modulo comunitario

fib-app

framework API di base dell'applicazione fibjs

installare

1
npm install fib-app [--save]

test

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

Tra questi personc'è 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 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 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.

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. idSono , updatedAt, createdAt, rispettivamente createdBy.

Tra questi id, updatedAtun createdAtsingolo campo viene creato e modificato automaticamente. createdByDevi 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 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, 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:

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 e createdAt: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 di ritorno keys, puoi personalizzare il contenuto restituito.Il keyscontenuto è una stringa di nomi di campo ,separati :

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

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

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

1
curl -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 keysimpostando . keysIl contenuto di è una stringa del nome di campo ,separata , ad esempio:

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

specificherà nameche ageverranno restituiti solo i campi e .

dove condizione di filtro

L'oggetto query può essere vincolato sotto forma di whereparametri .

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

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

whereIl valore di è una stringa JSON dopo urlencode, il contenuto è:{"name":"tom"}

Oltre a far corrispondere esattamente un dato valore, wheresupporta anche metodi di confronto, come contains. whereIl 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 skipl'opzione , puoi 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 limite di record

Tramite limitl'opzione , puoi limitare il numero limitdi record restituiti, il numero effettivo è 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 e 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

Incremento su richiesta Il numero totale di set di risultati countche possono essere restituiti 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à counte resultsdue 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 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

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 4
curl -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 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.

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:

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

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

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 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 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 di utenti 2
* Tutto 3

Durante il controllo delle autorizzazioni, corrisponderà prima alle autorizzazioni idcorrispondenti . Se non specificato, corrisponde rolealle 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 userdi utenti può leggere, l'utente 57fbbdb0a2400000dispone 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 trueper consentire l'accesso, falseper vietare l'accesso e arrayper consentire l'accesso solo ai campi specificati. deletee findnon sono accettati arraye vengono trattati arraycome 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 usersolo la lettura titlee detailgli 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 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à 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 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 le informazioni personali namee 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:

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

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 svgil diagramma delle classi di formato del modello di dati e salvarlo in un file per ottenere un'immagine simile alla seguente: diagramma