fib-app
marco API básico da aplicación fibjs
Instalar
1npm install fib-app [--save]
Proba
1npm 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
21const 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 person
está o módulo de definición do modelo, do seguinte xeito:
1
2
3
4
5
6
7module.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
4curl -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
, createdAt
campos individuais serán creados e modificados automaticamente. createdBy
Debe 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
4curl -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:
1curl -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
, updatedAt
e id
os 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 keys
contido personalizado que se pode devolver o keys
contido está en ,
cadeas de nome de campo divididas:
1curl -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
4curl -X PUT \
-H "Content-Type: application/json" \
-d '{"age": 25}' \
http://localhost/1.0/person/57fbbdb0a2400000
O obxecto devolto JSON conterá updatedAt
e un id
campo 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:
1curl -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:
1curl -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 keys
campo personalizado devolve o resultado para conter. keys
O contido está nunha ,
cadea de nome de campo dividida, por exemplo:
1curl -X GET http://localhost/1.0/person?keys=name%2Cage
A devolución especificada só name
e age
dous campos.
onde está o estado do filtro
By where
pode facer restricións no obxecto de consulta como parámetro.
where
O 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 where
como argumentos é incluír a clave e o valor axeitados. Por exemplo, se queremos buscar usuarios cuxo nome é tom, deberiamos construír a consulta así:
1curl -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, where
tamén se admiten métodos de comparación como a inclusión. where
Os 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 skip
opción, pode especificar o número de rexistros para omitir, para conseguir o efecto de virada.
1curl -X GET http://localhost/1.0/person?skip=100
límite devolve o límite de rexistro
Por limit
opción, pode limitar o número de rexistros devoltos, limit
os díxitos significativos de 1 a 1000 e os valores predeterminados a 100.
1curl -X GET http://localhost/1.0/person?limit=100
orde especifica o método de clasificación
Por order
opción definida para devolver o conxunto de resultados de Ordenación, antes de que o nome do campo conteña -
como hora inversa.
1curl -X GET http://localhost/1.0/person?order=-id
count devolve o número total de resultados
Cando se solicite aumentar count
o número total pode devolver un conxunto de resultados do contido especificado ao mesmo tempo.
1curl -X GET http://localhost/1.0/person?count=1&limit=1
Neste momento, os resultados de volta contén count
e results
dous 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
9module.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
4curl -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
4curl -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:
1curl -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
4curl -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:
1curl -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:
1curl -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
25const 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
}
}
};
}
});
};
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 role
e *
, id
representan un usuario específico, role
o 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á id
cos dereitos correspondentes, se non se especifica, os role
permisos 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 user
grupo de usuarios pode ler, o usuario 57fbbdb0a2400000
ten 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 true
para permitir o acceso, para false
prohibir o acceso para array
permitir só campos de acceso especificados. delete
E find
non acepta array
, se configuras array
entó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 user
só permite ler title
e detail
pó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
24module.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
41module.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 name
e 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:
1curl -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 svg
diagrama de clases de formato de modelo de datos , os ficheiros gardaranse nunha imaxe similar á seguinte: