Impresionante módulo de comunidad

fib-app

marco de api base de aplicación fibjs

Instalar

1
npm install fib-app [--save]

Prueba

1
npm test

Construyendo el script 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();

Donde person es el módulo de definición del Modelo, el contenido es el siguiente:

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

Esta es una definición estándar de ORM. También se pueden utilizar otras funciones de ORM, como verificación de tipo, eventos, etc.

Formato de datos API

Para las solicitudes POST y PUT, el cuerpo de la solicitud debe estar en formato JSON, y el Tipo de contenido del encabezado 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 las solicitudes, el formato de respuesta es un objeto JSON.

El éxito de una solicitud se indica mediante el código de estado HTTP. Un código de estado 2XX indica éxito y un 4XX indica que la solicitud falló. Cuando una solicitud falla, el cuerpo de la respuesta sigue siendo un objeto JSON, pero siempre contiene los campos de código y mensaje, que puede usar para la depuración. Por ejemplo, si falla la autenticación de un permiso de solicitud, se devuelve la siguiente información:

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

El código se divide en tres partes: los primeros tres dígitos indican el tipo de error, 05 indica el número de la tabla de datos y 01 indica el código de error detallado.

Para las solicitudes GET, generalmente se devuelven los datos del objeto. Dependiendo de la dirección de la solicitud GET, se puede devolver un objeto o una matriz. Por ejemplo:

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 especial

Hay cuatro campos de significado especial en los datos del objeto, que no se pueden cambiar a través de la API. Son id , updatedAt , createdAt , createdBy .

Los campos id , updatedAt y createdAt se crean y modifican automáticamente. createdBy necesita especificar el tipo por sí mismo.

API de acceso a objetos base

Después de completar dicha definición de datos, tiene un conjunto completo de llamadas de interfaz que se ajustan a la especificación de la API REST:

url método acción
/1.0/:className POST Crear nuevo objeto
/1.0/:className/:id OBTENER Leer objeto
/1.0/:className/:id PONER Modificar objeto
/1.0/:className/:id BORRAR Eliminar objeto
/1.0/:className OBTENER Consultar lista de objetos

Crear nuevo objeto

Para crear un nuevo objeto, se debe enviar una solicitud POST a la URL de la clase, que debe contener el objeto en sí. Por ejemplo, para crear un objeto como se describe 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

Cuando la creación es exitosa, la respuesta HTTP es 201 Creado, y el cuerpo de la respuesta es un objeto JSON que contiene el objectId y createdAt timestamp del nuevo objeto:

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

Leer objeto

Cuando crea un objeto, puede obtener su contenido enviando una solicitud GET a la ubicación del encabezado devuelto. Por ejemplo, para obtener el objeto que creamos arriba:

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

El cuerpo devuelto es un objeto JSON que contiene todos los campos proporcionados por el usuario más los campos 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" }

Por ajuste volverá campo keys , contenido personalizado puede ser devuelto, keys a un contenido que , cadenas de nombres de campo de segmentación:

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

Volveremos:

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

Modificar objeto

Para cambiar los datos que ya tiene un objeto, puede enviar una solicitud PUT a la URL correspondiente del objeto. Cualquier clave que no especifique no cambiará, por lo que solo puede actualizar un subconjunto de los datos del objeto. Por ejemplo, cambiemos un campo de edad de nuestro objeto:

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

El objeto JSON devuelto contendrá los campos updatedAt e id , que indican cuándo se produjo la actualización:

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

Eliminar objeto

Para eliminar un objeto, puede enviar una solicitud DELETE a la URL del objeto especificado, como:

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

Consultar lista de objetos

Al enviar una solicitud GET a la URL de la clase, puede obtener varios objetos a la vez sin ningún parámetro de URL. Aquí hay una manera simple de obtener todos los usuarios:

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

El valor devuelto es un objeto JSON que contiene el campo de resultados, y su valor es una lista de objetos:

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

teclas de personalización de campo

Al igual que con las consultas de objetos, puede personalizar los campos contenidos en los resultados devueltos configurando keys al consultar la lista. keys de un contenido a , cadenas de nombres de campo de segmentación, por ejemplo:

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

Se especificará para devolver solo age campos de name y age .

donde filtrar

A través de la forma del parámetro where , puede hacer restricciones en el objeto de consulta.

El valor del parámetro where debe estar codificado en JSON. Es decir, si observa la solicitud de URL que se emitió realmente, primero debe codificarse con JSON y luego codificarse con URL. La forma más fácil de usar el parámetro where es incluir la clave y el valor apropiados. Por ejemplo, si quisiéramos buscar un usuario llamado tom, construiríamos una consulta como esta:

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

El valor de where es una cadena JSON después de urlencode, el contenido es: {"name":"tom"}

Además de coincidir exactamente con un valor dado, where también admite métodos de comparación, como la inclusión. where parámetro where admite las siguientes opciones:

clave operación muestra
eq Igual a {"nombre": {"eq": "tom"}} o {"nombre": "tom"}
ne No igual {"nombre": {"ne": "tom"}}
gt Mayor que {"edad": {"gt": "24"}}
gte Mayor o igual que {"edad": {"gte": "24"}}
lt Menos de {"edad": {"lt": "24"}}
lte Menor o igual que {"edad": {"lte": "24"}}
como Consulta difusa {"nombre": {"me gusta": "% m"}}
no como Consulta difusa {"name": {"not_like": "% m"}}
entre Comparación de intervalos {"edad": {"entre": [22,25]}}
no_entre Comparación de intervalos {"age": {"not_between": [22,25]}}
en Enumeración {"nombre": {"en": ["tom", "lirio"]}}
no_en Enumeración {"nombre": {"not_in": ["tom", "lily"]}}
o Operación OR {"o": [{"nombre": "tom"}, {"edad": 24}]}

omitir omitir registros

Con la opción de skip , puede omitir el número especificado de registros y lograr el efecto de pasar las páginas.

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

limit devuelve el límite de registro

Con la opción de limit , puede limitar el número de registros devueltos. El número válido de limit es 1-1000, y el valor predeterminado es 100.

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

orden especifica el método de clasificación

Con la opción de order , puede establecer el método de clasificación del conjunto de resultados devuelto. Si el nombre del campo contiene- - se invertirá.

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

cuenta devuelve el número total de resultados

Un count creciente cuando se solicita puede devolver el número total de conjuntos de resultados mientras se devuelve el contenido especificado.

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

En este punto, el resultado devuelto contendrá dos campos, count y results , incluidos el total y el 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 objeto de extensión

Al definir hasOne y hasMany a través de orm, puede definir la asociación entre objetos y reflejarla en la API, por ejemplo:

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 objetos extendida

Aquí está la definición de API del objeto de extensión:

url método acción
/1.0/:className/:id/:extendName PONER Establecer objeto de extensión
/1.0/:className/:id/:extendName POST Crear objeto de extensión
/1.0/:className/:id/:extendName/:rid OBTENER Leer objeto extendido
/1.0/:className/:id/:extendName/:rid PONER Modificar objetos de extensión
/1.0/:className/:id/:extendName/:rid BORRAR Eliminar objetos extendidos
/1.0/:className/:id/:extendName OBTENER Consultar lista de objetos extendidos

Establecer objeto de extensión

Establecer un objeto extendido es establecer una relación entre dos objetos independientes. Por ejemplo, tom adoptó una mascota llamada cat, que se puede implementar con las siguientes operaciones:

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

La identificación del gato debe especificarse en el cuerpo de la llamada.

Crear objeto de extensión

Al crear directamente objetos extendidos, puede establecer relaciones entre objetos mientras los crea. Por ejemplo:

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

Se creará una mascota llamada cat y se asociará con tom.

Leer objeto extendido

Leer objetos extendidos es similar a leer objetos base, y también admite la opción de teclas:

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

Modificar objetos de extensión

Leer objetos extendidos es similar a leer objetos 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 objetos extendidos

Eliminar un objeto extendido no elimina el objeto en sí, solo libera la relación entre los objetos:

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

Consultar lista de objetos extendidos

La lista de objetos extendidos de la consulta es muy similar a la lista de objetos base de la consulta y también admite opciones como claves y filtrado de condiciones:

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

ACL

Los permisos de datos se pueden controlar definiendo ACL en los modelos. Por ejemplo:

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

Si no especifica una ACL al definir un modelo, es equivalente a establecer permisos predeterminados:

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

Asunto

Hay tres tipos de descripciones principales de ACL, id usuario, role usuario y * , id representa a un usuario específico, role representa a un usuario con un determinado rol y * representa a todos los usuarios:

Asunto Descripción Prioridad
id Identificación específica del usuario 1
papel Nombre del grupo de usuarios 2
* * Todos 3

Cuando se verifican los permisos, los permisos correspondientes a la id coincidir primero. Si no se especifica, se hacen coincidir los permisos correspondientes a la role usuario. Si aún se especifica, verifique si se especifica el permiso * y si no se especifica * , el permiso no está disponible.

Por ejemplo, la configuración de permisos anterior especifica que el grupo de user usuario puede leer. El usuario 57fbbdb0a2400000 tiene todos los permisos, mientras que otros usuarios no tienen ningún permiso.

Autoridad

ACL clasifica los permisos en cinco categorías según el comportamiento de la API:

Autoridad Descripción Tipos permitidos
crear Crear objeto verdadero / falso / matriz
leer Leer objeto verdadero / falso / matriz
escribir Modificar objeto verdadero / falso / matriz
eliminar Eliminar objeto verdadero / falso
encontrar Consultar lista de objetos verdadero / falso
* * Coincide con todos los permisos verdadero / falso / matriz

El permiso se establece en true para permitir el acceso, false para evitar el acceso y array para permitir el acceso solo a los campos especificados. delete y find no aceptan array . Si se establece la array , se tratan como true . Si el permiso especificado no existe, coincide con el permiso * bajo el mismo principal. Si no existe ninguno, vuelva a consultar el tema con la siguiente prioridad.

Por ejemplo, en el ejemplo anterior, si necesita configurar el user solo lea el title y los detail , y otros puedan leer el title , puede configurarlo 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 objeto

Los permisos de toda la clase se establecen en el Modelo. Si necesita establecer permisos en objetos específicos, puede lograr esto 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; } }); };

En este ejemplo, cuando el visitante es el objeto mismo, todas las operaciones están permitidas, de lo contrario, se prohíbe todo acceso. Los permisos se verifican de la siguiente manera:

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

Permisos de objeto extendidos

El control de acceso del objeto extendido es similar al del objeto base. La única diferencia es que la 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); };

En esta definición, cualquier persona puede buscar el name y el sex la información personal, y buscar y buscar libremente a sus pets .

Al verificar los derechos de acceso de los objetos extendidos, los permisos de objetos y los permisos de objetos extendidos se verifican por separado. Por ejemplo, la siguiente solicitud:

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

Los permisos se verifican de la siguiente manera:

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

Función

Puede definir API para Modelos, y para operaciones de datos complejas, puede completarlas con funciones personalizadas.

La mayoría de los permisos se pueden controlar a través de ACL. No es necesario utilizar funciones para completar los permisos basados ​​en objetos. La función se puede usar para completar permisos basados ​​en datos, como otorgar permisos a diferentes grupos de usuarios según el estado de aprobación. Y múltiples cambios, como la necesidad de modificar múltiples registros de la base de datos.

Trazar el modelo de datos

Después de completar la definición de datos, puede usar app.diagram() dibujar el diagrama de clase de formato svg del modelo de datos. Guarde en un archivo y obtendrá una imagen similar a la siguiente: diagrama