Удивительный модуль сообщества

Фибо-приложение

Основы API-интерфейса приложения fibjs

устанавливать

1
npm install fib-app [--save]

тест

1
npm test

Установить базовый скрипт

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

Где person является модулем определения модели, содержимое выглядит следующим образом:

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

Это стандартное определение orm и может также использовать другие функции orm, такие как проверка типов, события и т. Д.

Формат данных API

Для запросов POST и PUT тело запроса должно быть в формате JSON, а Content-Type заголовка HTTP должен быть установлен в 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

Для всех запросов формат ответа - это объект JSON.

Успешность запроса указывается кодом статуса HTTP. Код состояния 2XX указывает на успех, а код 4XX указывает на ошибку запроса. При сбое запроса тело ответа остается объектом JSON, но оно всегда содержит два поля: код и сообщение, которые можно использовать для отладки. Например, в случае сбоя запроса на авторизацию будет возвращена следующая информация:

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

Код разделен на три части, первые три 403 обозначают тип ошибки, 05 обозначает номер таблицы данных, а 01 обозначает подробный код ошибки.

Для запросов GET обычно возвращаются данные объекта. В зависимости от адреса запроса GET может быть возвращен объект или массив. Например:

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

Или:

1 2 3 4 5 6 7 8 9 10 11 12
[ { "name": "tom", "sex": "male", "age": 23 }, { "name": "lily", "sex": "female", "age": 22 } ]

Специальное поле

В данных объекта есть четыре поля со специальным значением, которые нельзя изменять через API. Они id , updatedAt , createdAt , createdBy , createdBy .

id , updatedAt , createdAt отдельных полях, будет автоматически создан и изменен. createdBy должен указать свой собственный тип.

API доступа к базовым объектам

После завершения такого определения данных у вас будет непосредственно набор интерфейсных вызовов, которые соответствуют спецификации API REST:

URL метод действие
/1.0/:className POST Создать новый объект
/1.0/:className/:id GET Читать объект
/1.0/:className/:id PUT Изменить объект
/1.0/:className/:id УДАЛИТЬ Удалить объект
/1.0/:className GET Список объектов запроса

Создать новый объект

Чтобы создать новый объект, необходимо отправить запрос POST на URL-адрес класса, который должен содержать сам объект. Например, чтобы создать объект, описанный выше:

1 2 3 4
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name": "tom","sex":"male","age":23}' \ http://localhost/1.0/person

Когда создание успешное, ответ HTTP создается 201, а тело ответа является объектом JSON, содержащим метку времени objectId и selectedAt нового объекта:

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

Читать объект

Когда вы создаете объект, вы можете получить его содержимое, отправив запрос GET в местоположение возвращаемого заголовка. Например, чтобы получить объект, который мы создали выше:

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

Возвращаемое тело - это объект JSON, содержащий все предоставленные пользователем поля, а также поля createdAt , updatedAt и 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" }

Устанавливая поле возвращает keys , настроить содержимое может быть возвращено, keys к содержанию к , сегментации строкам имени поля:

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

Вернется:

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

Изменить объект

Чтобы изменить данные, которые уже есть у объекта, вы можете отправить запрос PUT на соответствующий URL-адрес объекта. Любой ключ, который вы не укажете, не изменится, поэтому вы можете обновить только подмножество данных объекта. Например, давайте изменим поле возраста нашего объекта:

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

updatedAt объект JSON будет содержать updatedAt и id , указывающие, когда произошло обновление:

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

Удалить объект

Чтобы удалить объект, вы можете отправить запрос DELETE на URL указанного объекта, например:

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

Список объектов запроса

Вы можете получить несколько объектов одновременно, отправив запрос GET на URL класса без каких-либо параметров URL. Вот простой способ получить всех пользователей:

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

Возвращаемое значение представляет собой объект JSON, содержащий поле результатов, а его значение представляет собой список объектов:

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

Настройка ключевых полей

Как и в случае объектных запросов, вы можете установить keys чтобы настроить поля, включенные в возвращаемые результаты при запросе списка. keys от содержания к , строки имен сегментации поля, например:

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

Укажет, что возвращаются только два поля name и age .

где фильтр

Объект запроса может быть ограничен формой параметра where .

Значение параметра where должно быть закодировано в JSON. То есть, если вы посмотрите на запрос URL, который был фактически выполнен, он должен быть сначала закодирован в JSON, а затем закодирован в URL. Самый простой способ использовать параметр where - включить требуемый ключ и значение. Например, если мы хотим найти пользователя с именем tom, мы должны построить запрос следующим образом:

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

where строка JSON после urlencode, содержимое: {"name":"tom"}

В дополнение к точному соответствию заданному значению, where также поддерживаются методы сравнения, такие как включение. where поддерживает следующие параметры:

ключ операция образец
уравнение Равно {"name": {"eq": "tom"}} или {"name": "tom"}
Небраска Не равно {"name": {"ne": "tom"}}
GT Больше чем {"age": {"gt": "24"}}
GTE Больше или равно {"age": {"gte": "24"}}
л Меньше чем {"age": {"lt": "24"}}
Ге Меньше или равно {"age": {"lte": "24"}}
как Нечеткий запрос {"name": {"like": "% m"}}
not_like Нечеткий запрос {"name": {"not_like": "% m"}}
между Интервал сравнения {"age": {"Между": [22,25]}}
not_between Интервал сравнения {"age": {"not_between": [22,25]}}
в Перечислите {"name": {"in": ["tom", "lily"]}}
NOT_IN Перечислите {"name": {"not_in": ["tom", "lily"]}}
или ИЛИ операция {"or": [{"name": "tom"}, {"age": 24}]}

пропустить пропустить записи

С помощью опции skip вы можете пропустить указанное количество записей, чтобы добиться эффекта перелистывания страниц.

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

limit возвращает лимит записи

По limit варианту, вы можете ограничить количество записей , возвращаемых, limit значащих цифры от 1 до 1000, по умолчанию 100.

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

заказ определяет метод заказа

С помощью опции order вы можете установить метод сортировки возвращенного результирующего набора, если имя поля содержит - до того, как оно будет перевернуто.

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

count возвращает общее количество результатов

Увеличение count при запросе может вернуть общее количество наборов результатов при возврате указанного содержимого.

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

В это время возвращаемый результат будет содержать два поля count и results , которые содержат общее число и результат соответственно:

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

Создавайте расширенные объекты

Определяя hasOne и hasMany через orm, отношения между объектами могут быть определены и отражены в API, например:

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 расширенного доступа к объектам

Ниже приведено определение API объекта расширения:

URL метод действие
/1.0/:className/:id/:extendName PUT Установить расширенный объект
/1.0/:className/:id/:extendName POST Создать объект расширения
/1.0/:className/:id/:extendName/:rid GET Читать расширенные объекты
/1.0/:className/:id/:extendName/:rid PUT Изменить расширенные объекты
/1.0/:className/:id/:extendName/:rid УДАЛИТЬ Удалить расширенный объект
/1.0/:className/:id/:extendName GET Запрос расширенного списка объектов

Установить расширенный объект

Установка расширенного объекта заключается в установлении связи между двумя независимыми объектами. Например, Том принял домашнее животное по имени кошка, что может быть достигнуто с помощью следующих операций:

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

При вызове в теле должен быть указан id cat.

Создать объект расширения

Непосредственное создание расширенных объектов позволяет устанавливать связи между объектами при их создании. Например:

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

Домашнее животное по имени кошка будет создано и будет связано с Томом.

Читать расширенные объекты

Чтение расширенных объектов аналогично чтению базовых объектов, а также поддерживает параметр keys:

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

Изменить расширенные объекты

Чтение расширенных объектов очень похоже на чтение базовых объектов:

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

Удалить расширенный объект

Удаление расширенного объекта не удаляет сам объект, а только освобождает связь между объектами:

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

Запрос расширенного списка объектов

Список расширенных объектов запроса очень похож на список базовых объектов запроса, а также поддерживает такие параметры, как ключи и условная фильтрация:

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

ACL

Вы можете управлять разрешениями на данные, определяя 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
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 } } }; } }); };

Если ACL не указан при определении модели, это эквивалентно установке разрешений по умолчанию:

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

Основное тело

Существует три типа описания тела ACL: id пользователя, role пользователя и * , id представляет конкретного пользователя, role представляет пользователя с определенной ролью, * представляет всех пользователей:

Основное тело описание приоритет
идентификатор Конкретный идентификатор пользователя 1
роль Имя группы пользователей 2
* все 3

При проверке прав доступа, то первый матч id разрешения соответствуют, если не указано иное, соответствие пользователя role соответствующих полномочий, если до сих пор указано, он смотрит на ли * власти, если * также не указано, не имеют разрешения.

Например, вышеупомянутая конфигурация разрешения, указать user группа пользователей может читать, пользователь 57fbbdb0a2400000 иметь полный доступ, в то время как другие пользователи без какого - либо разрешения.

компетентность

ACL классифицирует разрешения на пять категорий на основе поведения API:

компетентность описание Разрешенные типы
создать Создать объект истина / ложь / массив
считывание Читать объект истина / ложь / массив
запись Изменить объект истина / ложь / массив
удалять Удалить объект правда / ложь
найти Список объектов запроса правда / ложь
* Соответствовать всем разрешениям истина / ложь / массив

Разрешения имеют значение true чтобы разрешить доступ, false чтобы запретить доступ, и array чтобы разрешить доступ только к указанным полям. delete и find не принимать array , если array установлен, он считается true . Если указанное разрешение не существует, оно совпадает с разрешением * той же темы. Если ничего не существует, запросите предмет следующего приоритета снова.

Например, в приведенном выше примере, если вам нужно настроить user чтение только title и detail , а другие могут читать title , вы можете установить его следующим образом:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "*": { "*": false, "read": ['title'] }, "57fbbdb0a2400000": { "*": true }, "roles": { "user": { "read": ['title', 'detail'] } } }

Объектные разрешения

Полномочия всего класса устанавливаются в модели. Если вам нужно установить разрешения для определенных объектов, вы можете установить 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; } }); };

В этом примере, когда посетителем является субъект, все операции будут разрешены, в противном случае весь доступ запрещен. Разрешения будут проверены в соответствии со следующими шагами:

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

Расширенные права доступа к объекту

Контроль прав доступа к расширенным объектам аналогичен базовым правам объектов, за исключением того, что 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); };

В этом определении каждый может проверить name и sex личной информации, а также свободно проверять и искать своих pets . Пользователь сам может использовать все свои собственные данные и иметь все разрешения для своей собственной информации о домашних животных.

При проверке прав доступа к расширенным объектам права на объекты и права на расширенные объекты проверяются отдельно. Например, следующий запрос:

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

Разрешения будут проверены в соответствии со следующими шагами:

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

функция

Для моделей могут быть определены API-интерфейсы. Для сложных операций с данными могут быть использованы пользовательские функции.

Подавляющее большинство разрешений может быть выполнено с помощью управления ACL, без необходимости выполнять основанные на объектах разрешения через Function. Функцию можно использовать для завершения разрешений на основе данных, таких как предоставление разрешений различным группам пользователей в зависимости от статуса утверждения. И много модификаций, таких как необходимость изменения нескольких записей базы данных.

Построить модель данных

После завершения определения данных вы можете использовать app.diagram() нарисовать диаграмму класса формата svg модели данных, и сохранить в файл, чтобы получить изображение, подобное следующему: диаграмма