Impresionante módulo de comunidad

fib-app

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

Instalar en pc

1
npm install fib-app [--save]

Prueba

1
npm test

Crea un script 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();

Entre ellos, person es el módulo de definición de Modelo con el siguiente contenido:

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 se pueden 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 falla de la solicitud. Cuando falla una solicitud, el cuerpo de la respuesta sigue siendo un objeto JSON, pero siempre contendrá dos campos, código y mensaje, que puede usar para la depuración. Por ejemplo, si falla una solicitud de autenticación de permiso, 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: los primeros tres dígitos 403 indican el tipo de error, 05 indican el número de la tabla de datos y 01 indican 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. como:

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

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

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

API de acceso a objetos básicos

Después de completar esta definición de datos, tendrá directamente un conjunto de llamadas de interfaz que se ajustan a la especificación de la API REST:

url método acción
/1.0/:className ENVIAR Crear nuevo objeto
/1.0/:className/:id OBTENER Leer objeto
/1.0/:className/:id PONER Modificar objeto
/1.0/:className/:id ELIMINAR 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 como se mencionó 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 incluye 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" }

Al configurar el campo devuelve keys , se puede devolver el contenido personalizado, keys a un contenido para , cadenas de nombre 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 existentes de un objeto, puede enviar una solicitud PUT a la URL correspondiente del objeto. Cualquier clave que no haya especificado no se 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. Lo siguiente es simplemente para 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 la consulta de objeto, puede personalizar los campos contenidos en el resultado devuelto configurando keys al consultar la lista. keys de un contenido para , cadenas de nombre de campo de segmentación, por ejemplo:

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

Especificará para devolver solo dos campos name y age .

donde la condición del filtro

El objeto de consulta se puede restringir en forma de parámetro where .

El valor del parámetro where debe estar codificado con JSON. En otras palabras, si observa la solicitud de URL que realmente se envió, 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 queremos buscar usuarios cuyo nombre sea tom, debemos construir la consulta de esta manera:

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:

llave operación muestra
eq igual {"nombre": {"eq": "tom"}} o {"nombre": "tom"}
nordeste no igual a {"nombre": {"ne": "tom"}}
gt más que el {"edad": {"gt": "24"}}
gte mayor o igual a {"edad": {"gte": "24"}}
lt Menos que {"edad": {"lt": "24"}}
lte Menos que o igual a {"edad": {"lte": "24"}}
me gusta Consulta difusa {"nombre": {"me gusta": "% m"}}
diferente a 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 enumerar {"nombre": {"en": ["tom", "lirio"]}}
no en enumerar {"nombre": {"not_in": ["tom", "lily"]}}
o Operación OR {"o": [{"nombre": "tom"}, {"edad": 24}]}

omitir omitir registro

A través de la opción de skip , puede omitir el número especificado de registros para lograr el efecto de pasar la página.

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

Use la opción de order para establecer el método de clasificación del conjunto de resultados devuelto. Si el nombre del campo contiene - antes de eso, está en orden inverso.

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

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 de extensión
/1.0/:className/:id/:extendName ENVIAR Crear un objeto de extensión
/1.0/:className/:id/:extendName/:rid OBTENER Leer objeto extendido
/1.0/:className/:id/:extendName/:rid PONER Modificar el objeto de extensión
/1.0/:className/:id/:extendName/:rid ELIMINAR Eliminar objeto de extensión
/1.0/:className/:id/:extendName OBTENER Consulta la lista de objetos extendidos

Establecer objeto de extensión

Establecer un objeto extendido es establecer una conexión entre dos objetos independientes. Por ejemplo, Tom ha adoptado una mascota llamada gato, 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 un objeto de extensión

Al crear directamente objetos extendidos, puede establecer conexiones entre objetos mientras crea objetos. como:

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 gato y se establecerá una relación de asociación 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 el objeto de extensión

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

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

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

Consulta la lista de objetos extendidos

Consultar la lista extendida de objetos es muy similar a consultar la lista básica de objetos, 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 las ACL del modelo. como:

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

Si no se especifica ninguna ACL al definir el modelo, es equivalente a establecer los permisos predeterminados:

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

cuerpo principal

Hay tres tipos de descripciones de asunto 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:

cuerpo principal descripción prioridad
carné de identidad ID de usuario específico 1
papel Nombre del grupo de usuarios 2
* * Todas 3

Al verificar los permisos, primero coincidirá con los permisos de id correspondientes, si no se especifica, la autoridad correspondiente de la role usuario correspondiente, si aún se especifica, analiza si la * autoridad, si * también no se especifica, no tiene permiso.

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 cinco tipos de permisos según el comportamiento de la API:

Autoridad descripción Tipo permitido
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 el acceso solo a los campos especificados. delete y find no acepta array , si la array está configurada, se considera true . Si la autoridad especificada no existe, coincidirá con la autoridad * 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 establecer que el user solo puede leer el title y los detail , y otras personas pueden 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 para toda la clase se establecen en el Modelo. Si necesita establecer permisos para 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 objeto mismo, se permitirán todas las operaciones; de lo contrario, se prohibirán todas las visitas. Los permisos se verificarán de acuerdo con los siguientes pasos:

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

Permisos de objeto extendidos

El control de permiso de acceso del objeto extendido es similar al del objeto base, la única diferencia es que debe especificarse por separado en la 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); };

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 propio usuario puede manipular todos sus datos y tiene todos los derechos sobre la información de sus mascotas.

Cuando se verifica la autoridad de acceso del objeto extendido, la autoridad del objeto y la autoridad del objeto extendido 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 el Modelo. Para operaciones de datos complejas, se puede completar personalizando la Función.

La gran mayoría de los permisos pueden ser controlados por ACL, y no se requiere ninguna función 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 modificaciones, como la necesidad de modificar múltiples registros de bases de datos.

Dibuja 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 el archivo para obtener una imagen similar a la siguiente: diagrama