Módulo de comunidad impresionante

fib-app

marco de api básico de la aplicación fibjs

Instalar en pc

1
npm install fib-app [--save]

Prueba

1
npm test

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

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 en 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 depurar. 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 individuales 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ásica

Después de completar esta definición de datos, tendrá directamente un conjunto completo de llamadas de interfaz que cumplen con 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 Lista de objetos de consulta

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 Created y el cuerpo de la respuesta es un objeto JSON, incluido el objectId y la marca de tiempo createdAt 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 establecer keys retorno de campo, se puede devolver contenido personalizado, keys para un contenido a , cadenas de nombres de campo de segmentación:

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

Regresará:

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

Lista de objetos de consulta

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

personalización del campo de claves

Al igual que la consulta de objetos, puede personalizar los campos contenidos en el resultado devuelto estableciendo keys al consultar la lista. keys de un contenido para , cadenas de nombres de campos de segmentación, por ejemplo:

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

Especificará devolver solo los dos campos name y age .

donde condición de filtro

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

El valor del parámetro where debe estar codificado en JSON. En otras palabras, si observa la solicitud de URL que realmente se envía, primero debe estar codificada en JSON y luego en la URL. La forma más sencilla de utilizar el parámetro where es incluir la clave y el valor adecuados. Por ejemplo, si queremos buscar usuarios cuyo nombre sea tom, deberíamos construir la consulta así:

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 hacer coincidir exactamente un valor dado, where también es compatible con los métodos de comparación, tales como la inclusión. where parámetro where admite las siguientes opciones:

llave operación muestra
eq igual {"name": {"eq": "tom"}} o {"name": "tom"}
nordeste no igual a {"nombre": {"ne": "tom"}}
gt mas que el {"age": {"gt": "24"}}
gte mayor o igual a {"age": {"gte": "24"}}
es Menos que {"age": {"lt": "24"}}
lte Menos que o igual a {"age": {"lte": "24"}}
me gusta Consulta difusa {"nombre": {"me gusta": "% m"}}
no como Consulta difusa {"nombre": {"not_like": "% m"}}
Entre Comparación de intervalo {"edad": {"entre": [22,25]}}
no entre Comparación de intervalo {"edad": {"not_between": [22,25]}}
en enumerar {"name": {"in": ["tom", "lily"]}}
no en enumerar {"nombre": {"not_in": ["tom", "lily"]}}
o O operación {"o": [{"nombre": "tom"}, {"edad": 24}]}

omitir omitir registro

Mediante 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

límite devuelve el límite de registro

Mediante 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

Utilice 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, está en orden inverso.

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

count devuelve el número total de resultados

El aumento del count al realizar la solicitud 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 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 los 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 extendido

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 Crea 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 Consultar 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, lo 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, el id de cat debe especificarse en el cuerpo.

Crea 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 muy similar a leer objetos base y también admite la opción de claves:

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

Consultar la lista de objetos extendidos

Consultar la lista de objetos extendida es muy similar a consultar la lista de objetos básica 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 modelos de ACL. 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 indica un usuario específico, role indica un usuario con una función determinada y * indica todos los usuarios:

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

Al verificar los permisos, primero hará coincidir los permisos de id correspondientes, si no se especifica, la autoridad correspondiente del role usuario coincidente, si aún se especifica, se observa si la * autoridad, si * tampoco se especifica, no tiene permiso.

Por ejemplo, en la configuración de permisos anterior, el grupo de user usuario se especifica para poder leer, y el usuario 57fbbdb0a2400000 tiene todos los permisos, mientras que otros usuarios no tienen permisos.

Autoridad

ACL categoriza 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 Lista de objetos de consulta verdadero Falso
* Coincidir 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 campos especificados. delete y find no aceptan array , si se establece array , se considera true . Si la autoridad especificada no existe, coincidirá con la * autoridad bajo el mismo principal. Si no existe, vuelva a consultar el asunto con la siguiente prioridad.

Por ejemplo, en el ejemplo anterior, si necesita establecer que el user solo pueda leer el title y los detail , y otros 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 propio visitante es el objeto, se permitirán todas las operaciones; de lo contrario, se prohíben todas las visitas. Los permisos se comprobarán de acuerdo con los siguientes pasos:

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

Permisos de objetos extendidos

El control de permisos de acceso del objeto extendido es similar al permiso de objeto básico, 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, cualquier persona puede comprobar el name y el sex la información personal, y comprobar y buscar libremente a sus pets . El propio usuario puede manipular todos sus datos y tiene todos los derechos sobre la información de su mascota.

Al verificar 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 comprobarán de acuerdo con los siguientes pasos:

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

Función

Se pueden definir API para el modelo y se pueden completar operaciones de datos complejas 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 utilizar 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 varios registros de la base de datos.

Dibujar el modelo de datos

Después de completar la definición de datos, puede usar app.diagram() dibujar el diagrama de clases de formato svg del modelo de datos y guardarlo en el archivo para obtener una imagen similar a la siguiente:diagrama