Awesome Community Module

fib-app

marco de la API básica de la aplicación fibjs

Instalar

1
npm install fib-app [--save]

Prueba

1
npm test

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

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, y también puede usar 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 un error de solicitud. Cuando una solicitud falla, el cuerpo de la respuesta sigue siendo un objeto JSON, pero siempre contiene dos campos, código y mensaje, que puede usar para depurar. Por ejemplo, si falla una solicitud de autorización, se devolverá 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, las tres primeras 403 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 con significados especiales en los datos del objeto, que no se pueden cambiar a través de la API. Son id , updatedAt , createdAt , createdBy .

Los campos individuales id , updatedAt , createdAt se crearán y modificarán automáticamente. createdBy necesita especificar su propio tipo.

API de acceso a objetos básicos

Después de completar dicha definición de datos, tendrá directamente un conjunto de llamadas de interfaz que cumplen con la especificación REST API:

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 el objeto descrito 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 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

Puede obtener varios objetos a la vez enviando una solicitud GET a la URL de la clase 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" } ]

Personalización de campo clave

Al igual que con las consultas de objetos, puede configurar las keys para personalizar los campos incluidos en los resultados devueltos 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

Especificará que solo se devuelven dos campos name y age .

donde filtrar

El objeto de consulta puede estar limitado por la forma del parámetro where .

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 en JSON y luego codificarse en la URL. La forma más fácil de usar el parámetro where es incluir la clave y el valor requeridos. Por ejemplo, si queremos buscar un usuario llamado tom, deberíamos construir una consulta como esta:

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

where hay 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}]}

saltar Saltar registros

A través de la opción de skip , puede omitir el número especificado de registros para 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

A través de la opción de limit , puede limitar el número de registros devueltos, el número efectivo de limit es 1-1000, el valor predeterminado es 100.

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

orden especifica el método de pedido

Con la opción de order , puede establecer el método de clasificación del conjunto de resultados devuelto. Cuando el nombre del campo contiene- - está en orden inverso.

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

cuenta devuelve el número total de resultados

El 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 momento, el resultado devuelto contendrá dos campos, count y results , que contienen el número 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 objetos extendidos

Al definir hasOne y hasMany a través de orm, la relación entre objetos se puede definir y reflejar 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

La siguiente es la definición de API del objeto de extensión:

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

Establecer objeto extendido

Establecer un objeto extendido es establecer una conexión entre dos objetos independientes. Por ejemplo, tom ha adoptado una mascota llamada cat, que se puede lograr 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

En la llamada, la identificación de cat debe especificarse en el cuerpo.

Crear objeto de extensión

La creación directa de objetos extendidos le permite establecer conexiones 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 objetos extendidos

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 extendidos

Leer objetos extendidos es muy 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 objeto extendido

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 básicos de la consulta, y también admite opciones como claves y filtrado condicional:

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

ACL

Puede controlar los permisos de datos definiendo la ACL del modelo. 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 la ACL no se especifica al definir el modelo, es equivalente a establecer los permisos predeterminados:

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

Cuerpo principal

Hay tres tipos de descripción del cuerpo de ACL, id usuario, role usuario y * , id representa a un usuario específico, role representa a un usuario con un determinado rol, * representa a todos los usuarios:

Cuerpo principal Descripción Prioridad
id ID de usuario específico 1
papel Nombre del grupo de usuarios 2
* * Todos 3

Cuando la comprobación de permisos, primero que coincida con id permisos corresponden, si no se especifica, igualando usuario role autoridad correspondiente, si todavía está especificado, se analiza si el * autoridad, si * Tampoco se especifica, no tiene permiso.

Por ejemplo, la configuración de permisos anterior especifica que se puede leer el grupo de user usuario. 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

Los permisos se establecen en true para permitir el acceso, false para prohibir el acceso y array para permitir solo el acceso a campos específicos. delete y find no acepta array , si la array está configurada, se considera true . Si el permiso especificado no existe, coincide con el permiso * bajo el mismo asunto. Si no existe ninguno, vuelva a consultar el tema de 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 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; } }); };

En este ejemplo, cuando el visitante es el sujeto, se permitirán todas las operaciones; de lo contrario, se prohíbe todo acceso. Los permisos se verificarán de acuerdo con los siguientes pasos:

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

Permisos de objeto extendidos

El control de los derechos de acceso de los objetos extendidos es similar a los derechos básicos de los objetos, excepto 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, cualquiera puede verificar el name y el sex la información personal, y verificar y buscar libremente a sus pets . El usuario mismo puede operar todos sus datos y tener todos los permisos de su propia información sobre mascotas.

Al verificar los derechos de acceso de los objetos extendidos, los derechos de los objetos y los derechos de los 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 verificarán de acuerdo con los siguientes pasos:

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

Función

Las API se pueden definir para Modelos. Para operaciones de datos complejas, se pueden usar Funciones personalizadas para completar.

La gran mayoría de los permisos se pueden completar a través del control de ACL, sin la necesidad de completar permisos basados ​​en objetos a través de la función. 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 muchas modificaciones, como la necesidad de modificar múltiples registros de bases 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 y guardarlo en un archivo para obtener una imagen similar a la siguiente: diagrama