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

fib-app

Основа 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.

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

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

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

url метод действие
/1.0/:className ПОЧТА Создать новый объект
/1.0/:className/:id ПОЛУЧАТЬ Прочитать объект
/1.0/:className/:id ПОЛОЖИЛ Изменить объект
/1.0/:className/:id УДАЛЯТЬ Удалить объект
/1.0/:className ПОЛУЧАТЬ Список объектов запроса

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

Чтобы создать новый объект, необходимо отправить запрос 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 Created, а тело ответа - это объект JSON, включая objectId и временную метку createdAt нового объекта:

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

Прочитать объект

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

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

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два поля.

где условие фильтра

By 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"}
ne не равно {"name": {"ne": "tom"}}
gt больше чем {"возраст": {"gt": "24"}}
gte больше или равно {"возраст": {"gte": "24"}}
lt Меньше, чем {"возраст": {"lt": "24"}}
lte Меньше или равно {"возраст": {"lte": "24"}}
нравиться Нечеткий запрос {"name": {"like": "% m"}}
не как Нечеткий запрос {"name": {"not_like": "% m"}}
между Сравнение интервалов {"возраст": {"между": [22,25]}}
not_between Сравнение интервалов {"возраст": {"not_between": [22,25]}}
в перечислять {"имя": {"в": ["том", "лилия"]}}
не в перечислять {"name": {"not_in": ["tom", "lily"]}}
или ИЛИ операция {"или": [{"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 ПОЛОЖИЛ Установить объект расширения
/1.0/:className/:id/:extendName ПОЧТА Создать объект расширения
/1.0/:className/:id/:extendName/:rid ПОЛУЧАТЬ Читать расширенный объект
/1.0/:className/:id/:extendName/:rid ПОЛОЖИЛ Измените объект расширения
/1.0/:className/:id/:extendName/:rid УДАЛЯТЬ Удалить объект расширения
/1.0/:className/:id/:extendName ПОЛУЧАТЬ Запросить список расширенных объектов

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

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

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

В вызове необходимо указать id кота в теле.

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

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

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

Будет создано домашнее животное по имени кошка и будут установлены отношения ассоциации с томом.

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

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

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: Stringnote: 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, если установить arraythen расценивать как 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, и для выполнения разрешений на основе объектов не требуется никаких функций. Функцию можно использовать для выполнения разрешений на основе данных, таких как предоставление разрешений различным группам пользователей на основе статуса утверждения. И несколько модификаций, например, необходимость изменить несколько записей базы данных.

Нарисуйте модель данных

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