Módulo comunitario incrible

fib-app

marco API básico da aplicación fibjs

Instalar

1
npm install fib-app [--save]

Proba

1
npm test

Constrúe un 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, do seguinte xeito:

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

Esta é unha definición estándar de orm e tamén se poden usar outras funcións de orm, como comprobació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 establecerse 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 éxito dunha solicitude indícase co código de estado HTTP. Un código de estado 2XX indica o éxito e un 4XX indica o fallo da solicitude. Cando falla unha solicitude, o corpo da resposta segue sendo un obxecto JSON, pero sempre conterá os dous campos de código e mensaxe, que pode empregar para a depuración. Por exemplo, se falla unha solicitude de autenticación de permiso, 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 divídese en tres partes: os tres primeiros díxitos 403 indican o tipo de erro, 05 indican o número da táboa de datos e 01 indican o código de erro detallado.

Para unha solicitude GET, normalmente devólvense os datos do obxecto. Dependendo do 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 } ]

Campo especial

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

Onde id, updatedAt, createdAtcampos individuais serán creados e modificados automaticamente. createdByDebe especificar vostede mesmo o tipo.

API básica de acceso a obxectos

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

url método acción
/1.0/:Nome da clase POST Crear novo obxecto
/1.0/:className/:id CONSEGUIR Ler obxecto
/1.0/:className/:id POÑER Modifica o obxecto
/1.0/:className/:id BORRAR Eliminar obxecto
/1.0/:Nome da clase CONSEGUIR Lista de obxectos de consulta

Crear novo obxecto

Para crear un novo obxecto, débese enviar unha solicitude POST á URL da clase, que debe conter o propio obxecto. Por exemplo, para crear o obxecto como se mencionou anteriormente:

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 ten éxito, a resposta HTTP é 201 Creada e o corpo da resposta é un obxecto JSON, incluído o objectId e createdAt timestamp do novo obxecto:

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

Ler obxecto

Cando crea un obxecto, pode obter 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 retorna un obxecto JSON contén todo en conxunto co campo fornecido polo usuario createdAt, updatedAte idos campos:

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

Devolve o campo proporcionando keyscontido personalizado que se pode devolver o keyscontido está en ,cadeas de nome de campo divididas:

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

Volverá:

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

Modifica o obxecto

Para cambiar os datos existentes dun obxecto, pode enviar unha solicitude PUT ao URL correspondente do obxecto. Calquera clave que non especifique non se cambiará, polo que só pode actualizar un subconxunto dos datos do obxecto. Por exemplo, cambiemos 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 devolto JSON conterá updatedAte un idcampo que indican que se produciu a actualización á vez:

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, como:

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

Lista de obxectos de consulta

Ao enviar unha solicitude GET ao URL da clase, pode obter varios obxectos á vez sen ningún parámetro de URL. O seguinte é simplemente conseguir que 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 e o seu 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 teclas

Do mesmo xeito que coa consulta de obxectos, pode configurar a lista de consultas que o keyscampo personalizado devolve o resultado para conter. keysO contido está nunha ,cadea de nome de campo dividida, por exemplo:

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

A devolución especificada só namee agedous campos.

onde está o estado do filtro

By wherepode facer restricións no obxecto de consulta como parámetro.

whereO valor do parámetro debe estar codificado en JSON. Noutras palabras, se observas a solicitude de URL que realmente se enviou, primeiro debería estar codificada por JSON e logo codificada por URL. O máis doado de usar wherecomo argumentos é incluír a clave e o valor axeitados. Por exemplo, se queremos buscar usuarios cuxo nome é tom, deberiamos construír a consulta así:

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

where O valor é unha cadea JSON despois do código de url, o contido é:{"name":"tom"}

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

clave operación mostra
eq igual {"name": {"eq": "tom"}} ou {"name": "tom"}
ne non igual a {"nome": {"ne": "tom"}}
gt máis que o {"age": {"gt": "24"}}
gte maior ou igual a {"age": {"gte": "24"}}
lt Menos de {"idade": {"lt": "24"}}
lte Menor ou igual a {"age": {"lte": "24"}}
como Consulta difusa {"name": {"like": "% m"}}
non_como Consulta difusa {"name": {"not_like": "% m"}}
entre Comparación de intervalos {"idade": {"entre": [22,25]}}
non_entre Comparación de intervalos {"age": {"not_between": [22,25]}}
dentro enumerar {"nome": {"en": ["tom", "lirio"]}}
non_in enumerar {"name": {"not_in": ["tom", "lily"]}}
ou OU operación {"or": [{"name": "tom"}, {"age": 24}]}

saltar saltar rexistros

Por skipopción, pode especificar o número de rexistros para omitir, para conseguir o efecto de virada.

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

límite devolve o límite de rexistro

Por limitopción, pode limitar o número de rexistros devoltos, limitos díxitos significativos de 1 a 1000 e os valores predeterminados a 100.

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

orde especifica o método de clasificación

Por orderopción definida para devolver o conxunto de resultados de Ordenación, antes de que o nome do campo conteña -como hora inversa.

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

count devolve o número total de resultados

Cando se solicite aumentar counto número total pode devolver un conxunto de resultados do contido especificado ao mesmo tempo.

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

Neste momento, os resultados de volta contén counte resultsdous campos, e cada unha comprendendo un número total de resultados:

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 un obxecto de extensión

Ao definir hasOne e hasMany a través de orm, a relación de asociación entre obxectos pódese definir e reflectir 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 ampliada

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 obxecto de extensión
/1.0/:ClassName/:id/:extendName POST Crea un obxecto de extensión
/1.0/:className/:id/:extendName/:rid CONSEGUIR Ler obxecto ampliado
/1.0/:className/:id/:extendName/:rid POÑER Modifique o obxecto de extensión
/1.0/:className/:id/:extendName/:rid BORRAR Eliminar obxecto de extensión
/1.0/:ClassName/:id/:extendName CONSEGUIR Consulte a lista de obxectos estendidos

Establecer obxecto de extensión

Establecer un obxecto estendido é establecer unha conexión entre dous obxectos independentes. Por exemplo, Tom adoptou unha mascota chamada gato, que se pode conseguir coas seguintes operacións:

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 identificador de gato debe especificarse no corpo.

Crea un obxecto de extensión

Ao crear directamente obxectos estendidos, pode establecer conexións entre obxectos mentres crea obxectos. 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 establecerase unha relación de asociación con Tom.

Ler obxecto ampliado

Ler obxectos estendidos é moi similar á 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

Modifique o obxecto de extensión

Ler obxectos estendidos é moi similar á 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 de extensión

Ao eliminar un obxecto estendido non se elimina o obxecto en si, senón que só se elimina a relación entre os obxectos:

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

Consulte a lista de obxectos estendidos

A consulta da lista de obxectos ampliada é moi similar á consulta da lista de obxectos básica e tamén admite opcións como as claves e o 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 cando se define o modelo, equivale a establecer os permisos predeterminados:

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

corpo principal

Hai tres descricións ACL principais: usuario id, usuario rolee *, idrepresentan un usuario específico, roleo que indica que o usuario ten un papel, *significa que todos os usuarios:

corpo principal describir prioridade
id A identificación do usuario específico 1
papel Nome do grupo de usuarios 2
* Todo 3

Ao comprobar os privilexios, o primeiro coincidirá idcos dereitos correspondentes, se non se especifica, os rolepermisos de usuario coincidentes correspondentes aínda se se especifican, para ver se a *autoridade designada , se *non se especifica, non ten permiso.

Por exemplo, a configuración de permisos anterior, especifica que o usergrupo de usuarios pode ler, o usuario 57fbbdb0a2400000ten plenos dereitos, mentres que outros usuarios sen ningún permiso.

Autoridade

ACL clasifica cinco tipos de permisos en función do comportamento da API:

Autoridade describir Tipo permitido
crear Crea un obxecto verdadeiro / falso / matriz
ler Ler obxecto verdadeiro / falso / matriz
escribir Modifica o obxecto verdadeiro / falso / matriz
eliminar Eliminar obxecto verdadeiro / falso
atopar Lista de obxectos de consulta verdadeiro / falso
* Coincide con todos os permisos verdadeiro / falso / matriz

Permisos desenvolvidos truepara permitir o acceso, para falseprohibir o acceso para arraypermitir só campos de acceso especificados. deleteE findnon acepta array, se configuras arrayentón considerado como true. Se o permiso especificado non existe, entón a seguinte coincidencia coa *autoridade principal . Se non existe ningún, consulte de novo o asunto da seguinte prioridade.

Exemplos do exemplo anterior, se se precisa establecer usersó permite ler titlee detailpódense ler outros title, pódese configurar de xeito que:

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 de toda a clase configúranse no modelo. Se precisa establecer permisos para obxectos específicos, pode configurar OACL para lograr:

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 suxeito, permitiranse todas as operacións, se non, estarán prohibidas todas as visitas. Os permisos comprobaranse segundo os seguintes pasos:

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

Permisos de obxectos ampliados

O control de permisos de acceso do obxecto estendido é similar ao permiso de obxecto básico, a única diferenza é que debe especificarse por separado na ACL:

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

Esta definición, calquera pode acceder á información persoal namee sex, e de acceso libre e buscalo pets, son o usuario que pode operar todos os seus datos e todos os dereitos para ter a súa propia información sobre mascotas.

Ao comprobar a autorización de acceso do obxecto estendido, a autorización do obxecto e a autorización do obxecto estendido compróbanse por separado. Por exemplo, a seguinte solicitude:

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

Os permisos comprobaranse segundo os seguintes pasos:

  • 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 pódense completar operacións de datos complexas personalizando a función.

ACL pode controlar a gran maioría dos permisos e non se require ningunha función para completar os permisos baseados en obxectos. 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 varias modificacións, como a necesidade de modificar varios rexistros de bases de datos.

Debuxa o modelo de datos

Despois de completar a definición de datos pode usarse app.diagram()para debuxar un svgdiagrama de clases de formato de modelo de datos , os ficheiros gardaranse nunha imaxe similar á seguinte: diagrama