Impresionante módulo comunitario

aplicación fib

marco básico de api da aplicación fibjs

Instalar

1
npm install fib-app [--save]

Proba

1
npm test

Crear guión básico

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

Onde personestá o módulo de definición do modelo, o contido é o seguinte:

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

Esta é unha definición ORM estándar, e tamén pode usar outras funcións ORM, como a verificación de tipos, eventos, etc.

Formato de datos API

Para as solicitudes POST e PUT, o corpo da solicitude debe estar en formato JSON e o tipo de contido da cabeceira HTTP debe configurarse en 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

Para todas as solicitudes, o formato de resposta é un obxecto JSON.

O código de estado HTTP indica se unha solicitude foi exitosa ou non. Un código de estado 2XX indica éxito, mentres que un código de estado 4XX indica que a solicitude fallou. Cando unha solicitude falla, o corpo da resposta segue sendo un obxecto JSON, pero sempre contén os campos de código e mensaxe, que podes usar para depurar. Por exemplo, se falla unha solicitude de autenticación de permisos, devolverase a seguinte información:

1 2 3 4
{ "code": 4030501, "message": "The operation isn’t allowed for clients due to class-level permissions." }

O código de código divídese en tres partes: os tres primeiros díxitos 403 representan o tipo de erro, 05 o número da folla de datos e 01 o código de erro detallado.

Para as solicitudes GET, adoitan devolverse os datos do obxecto. Segundo o enderezo da solicitude GET, pódese devolver un obxecto ou unha matriz. por exemplo:

1 2 3 4 5
{ "name": "tom", "sex": "male", "age": 23 }

ou:

1 2 3 4 5 6 7 8 9 10 11 12
[ { "name": "tom", "sex": "male", "age": 23 }, { "name": "lily", "sex": "female", "age": 22 } ]

campos especiais

Nos datos do obxecto, hai catro campos con significados especiais que non se permiten cambiar a través da API. Son id, updatedAt, createdAt, respectivamente createdBy.

Entre eles id, updatedAt, createdAtcrearanse e modificaranse automaticamente campos únicos. createdByDebe especificar o tipo vostede mesmo.

API básica de acceso a obxectos

Despois de completar esta definición de datos, terá directamente un conxunto de chamadas de interface que cumpran coa especificación da API REST:

url método acción
/1.0/:className POST Crea un novo obxecto
/1.0/:className/:id CONSEGUIR Ler obxecto
/1.0/:className/:id POÑER Modificar obxecto
/1.0/:className/:id ELIMINAR Eliminar obxecto
/1.0/:className CONSEGUIR Consulta a lista de obxectos

Crea un novo obxecto

Para crear un novo obxecto, debe enviarse unha solicitude POST ao URL da clase, que debe incluír o propio obxecto. Por exemplo, para crear o obxecto mostrado arriba:

1 2 3 4
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name": "tom","sex":"male","age":23}' \ http://localhost/1.0/person

Cando a creación é exitosa, o retorno HTTP é 201 Created, e o corpo da resposta é un obxecto JSON que contén o objectId e createdAt timestamp do novo obxecto:

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

Ler obxecto

Cando creas un obxecto, podes recuperar o seu contido enviando unha solicitude GET á localización da cabeceira devolta. Por exemplo, para obter o obxecto que creamos anteriormente:

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

O corpo devolto é un obxecto JSON que contén todos os campos proporcionados polo usuario máis os campos createdAt, updatedAte 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" }

Ao configurar o campo de devolución keys, pode personalizar o contido devolto, keysque é unha ,cadea de nomes de campo separados por:

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

volverá:

1 2 3 4
{ "name": "tom", "sex": "male" }

Modificar obxecto

Para cambiar os datos existentes dun obxecto, pode enviar unha solicitude PUT ao URL correspondente do obxecto. As claves que non especifiquen non se modificarán, polo que só pode actualizar un subconxunto dos datos do obxecto. Por exemplo, imos cambiar un campo de idade do noso obxecto:

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

O obxecto JSON devolto conterá updatedAte idcampos que indican cando se produciu a actualización:

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

Eliminar obxecto

Para eliminar un obxecto, pode enviar unha solicitude DELETE ao URL do obxecto especificado, por exemplo:

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

Consulta a lista de obxectos

Podes obter varios obxectos á vez enviando unha solicitude GET ao URL da clase, sen ningún parámetro de URL. Aquí tes como conseguir simplemente todos os usuarios:

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

O valor devolto é un obxecto JSON que contén o campo de resultados, cuxo valor é unha lista de obxectos:

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" } ]

personalización do campo de claves

Do mesmo xeito que a consulta de obxectos, pode keyspersonalizar os campos incluídos nos resultados devoltos configurando cando se consulta a lista. keysO contido é unha ,cadea de nomes de campo separados por , por exemplo:

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

Especificará que só se devolverán os campos namee .age

onde condición do filtro

whereO obxecto de consulta pódese restrinxir en forma de parámetros.

whereO valor do parámetro debe estar codificado en JSON. É dicir, se observas a solicitude de URL real que se fai, primeiro debería codificarse en JSON e despois codificarse en URL. O wherexeito máis sinxelo de usar os parámetros é incluír a clave e o valor axeitados. Por exemplo, se quixeramos buscar usuarios chamados tom, construíriamos a consulta así:

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

whereO valor é unha cadea JSON codificada en url, o contido é:{"name":"tom"}

Ademais de facer coincidir exactamente un valor determinado, wheretamén se admiten métodos de comparación como a inclusión. whereOs parámetros admiten as seguintes opcións:

chave operación mostra
eq iguais {"name":{"eq":"tom"}} ou {"name":"tom"}
ne non igual a {"name":{"ne":"tom"}}
gt máis que o {"age":{"gt":"24"}}
gte maior ou igual a {"age":{"gte":"24"}}
lt menos que {"age":{"lt":"24"}}
lte menor ou igual a {"age":{"lte":"24"}}
como consulta difusa {"name":{"gústame":"%m"}}
non_gústame consulta difusa {"name":{"not_like":"%m"}}
entre Comparación de intervalos {"idade":{"entre":[22,25]}}
non_entre Comparación de intervalos {"idade":{"non_entre":[22,25]}}
en enumerar {"nome":{"en":["tom","lirio"]}}
non_en enumerar {"name":{"not_in":["tom","lirio"]}}
ou OR operación {"ou":[{"nome":"tom"},{"idade":24}]}

saltar rexistros

A través skipda opción, pode saltar o número especificado de rexistros para lograr o efecto de pasar páxina.

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

límite devolve o límite de rexistro

A través limitda opción, pode limitar o número de rexistros devoltos. limitOs números válidos son 1-1000 e o predeterminado é 100.

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

orde especifica o método de clasificación

Use ordera opción para establecer o método de ordenación do conxunto de resultados devolto. Cando o nome do campo contén antes, -faise en orde inversa.

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

count devolve o número total de resultados

Incrementado a petición countO número total de conxuntos de resultados que se poden devolver mentres se devolve o contido especificado.

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

Neste momento, o resultado devolto conterá dous campos: counte results, que conteñen o número total e o resultado respectivamente:

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" } ] }

Crear obxecto de extensión

Ao definir hasOne e hasMany mediante ORM, pode definir a asociación entre obxectos e reflectila na API, por exemplo:

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 de acceso a obxectos estendido

A seguinte é a definición da API do obxecto de extensión:

url método acción
/1.0/:className/:id/:extendName POÑER Establecer o obxecto de extensión
/1.0/:className/:id/:extendName POST Crear obxecto de extensión
/1.0/:className/:id/:extendName/:rid CONSEGUIR Ler obxecto de extensión
/1.0/:className/:id/:extendName/:rid POÑER Modificar o obxecto de extensión
/1.0/:className/:id/:extendName/:rid ELIMINAR Eliminar obxecto estendido
/1.0/:className/:id/:extendName CONSEGUIR Consulta a lista de obxectos estendida

Establecer o obxecto de extensión

Establecer un obxecto de extensión é establecer unha relación entre dous obxectos independentes. Por exemplo, se Tom adopta unha mascota chamada gato, pode usar as seguintes operacións para conseguilo:

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

Na chamada, o ID do gato debe especificarse no corpo.

Crear obxecto de extensión

A creación directa de obxectos estendidos pode establecer conexións entre obxectos mentres se crean. por exemplo:

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

Crearase unha mascota chamada gato e asociarase a Tom.

Ler obxecto de extensión

A lectura de obxectos estendidos é moi semellante á lectura de obxectos base e tamén admite a opción de teclas:

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

Modificar o obxecto de extensión

A lectura de obxectos estendidos é moi semellante á lectura de obxectos 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

Eliminar obxecto estendido

A eliminación dun obxecto estendido non elimina o propio obxecto, só disolve a relación entre os obxectos:

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

Consulta a lista de obxectos estendida

Consultar a lista de obxectos estendida é moi semellante á consulta da lista básica de obxectos e tamén admite opcións como claves e filtrado condicional:

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

ACL

Os permisos de datos pódense controlar definindo a ACL do modelo. por exemplo:

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 se especifica ningunha ACL ao definir o modelo, equivale a establecer os permisos predeterminados:

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

corpo principal

Hai tres tipos de descricións de asuntos ACL: usuario id, usuario rolee *, idque representan un usuario específico, rolerepresentan usuarios cun determinado rol e *representan a todos os usuarios:

corpo principal describir prioridade
ID ID de usuario específico 1
papel Nome do grupo de usuarios 2
* Todos 3

Ao comprobar os permisos, primeiro coincidirá idcos permisos correspondentes. Se non se especifica, entón coincidirá rolecos permisos correspondentes do usuario. Se aínda se especifica, comprobe se *os permisos de están especificados. Se *non se especifica, non hai ningún permiso.

Por exemplo, na configuración de permisos anterior, userespecifícase o grupo de usuarios para poder ler. O usuario 57fbbdb0a2400000ten todos os permisos, pero os demais usuarios non teñen ningún permiso.

Permisos

ACL clasifica os permisos en cinco categorías en función do comportamento da API:

Permisos describir tipos permitidos
crear Crear obxecto verdadeiro/falso/matriz
ler Ler obxecto verdadeiro/falso/matriz
escribir Modificar obxecto verdadeiro/falso/matriz
eliminar Eliminar obxecto verdadeiro/falso
atopar Consulta a lista de obxectos verdadeiro/falso
* Coincide todos os permisos verdadeiro/falso/matriz

Os permisos están configurados truepara permitir o acceso, falsepara denegar o acceso e arraysó para permitir o acceso a campos especificados. deletee findnon se aceptan e trátanse igual arrayse se establecen . Se o permiso especificado non existe, coincidirán os permisos do mesmo asunto. Se non existe ningunha das dúas, consulta de novo o asunto do seguinte nivel de prioridade.arraytrue*

Por exemplo, no exemplo anterior, se precisa configurar usersó a lectura titlee detailpermitir que outros lean title, pode configuralo así:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "*": { "*": false, "read": ['title'] }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": ['title', 'detail'] } } }

Permisos de obxectos

Os permisos establecidos no Modelo son os permisos de toda a clase. Se precisas establecer permisos en obxectos específicos, podes facelo configurando 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; } }); };

Neste exemplo, cando o visitante é o propio obxecto, permitiranse todas as operacións, en caso contrario prohibirase todo o acceso. Os permisos compróbanse do seguinte xeito:

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

Permisos de obxectos estendidos

O control de permisos de acceso dos obxectos estendidos é similar aos permisos dos obxectos básicos. A única diferenza é que a ACL debe especificarse por separado:

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

Nesta definición, calquera pode comprobar a namesuma da información persoal sex, e libremente consultala e buscala.O petspropio usuario pode operar todos os seus propios datos e ter permisos completos para a información da súa propia mascota.

Ao comprobar os permisos de acceso para obxectos estendidos, compróbanse por separado os permisos de obxecto e os permisos de obxecto estendidos. Por exemplo, a seguinte solicitude:

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

Os permisos compróbanse do seguinte xeito:

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

Función

As API pódense definir para o modelo e as operacións de datos complexas pódense completar mediante funcións personalizadas.

A maioría dos permisos pódense controlar mediante ACL, e os permisos baseados en obxectos non precisan implementarse mediante Function. A función pódese usar para completar permisos baseados en datos, como conceder permisos a diferentes grupos de usuarios en función do estado de aprobación. E múltiples modificacións, como a necesidade de modificar varios rexistros de bases de datos.

Debuxar modelo de datos

Despois de completar a definición de datos, pode usar para app.diagram()debuxar o diagrama de clases de formato do modelo de datos svg. Cando garde nun ficheiro, obterá unha imaxe similar á seguinte: diagrama