Потрясающий модуль сообщества

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

Базовая платформа 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. Тип необходимо указать самостоятельно.createdAtcreatedBy

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

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

URL метод действие
/1.0/:имякласса ПОЧТА Создать новый объект
/1.0/:имякласса/:id ПОЛУЧАТЬ Чтение объекта
/1.0/:имякласса/:id ПОМЕЩАТЬ Изменить объект
/1.0/:имякласса/:id УДАЛИТЬ Удалить объект
/1.0/:имякласса ПОЛУЧАТЬ Список объектов запроса

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

Чтобы создать новый объект, необходимо отправить запрос 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 и временную метку CreateAt нового объекта:

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

где состояние фильтра

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

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

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"}
пе не равен {"имя":{"не":"том"}}
гт больше, чем {"возраст":{"gt":"24"}}
гте больше или равно {"возраст":{"gte":"24"}}
лт меньше, чем {"возраст":{"lt":"24"}}
лте меньше или равно {"возраст":{"lte":"24"}}
нравиться нечеткий запрос {"имя":{"нравится":"%m"}}
не как нечеткий запрос {"name":{"not_like":"%m"}}
между Сравнение интервалов {"возраст":{"между":[22,25]}}
не_между Сравнение интервалов {"возраст":{"not_between":[22,25]}}
в перечислять {"name":{"in":["том","лилия"]}}
не в перечислять {"name":{"not_in":["том","лилия"]}}
или операция ИЛИ {"или":[{"имя":"том"},{"возраст":24}]}

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

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

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

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

С помощью limitэтой опции вы можете ограничить количество возвращаемых записей. limitДопустимые числа: 1–1000, значение по умолчанию — 100.

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

order определяет метод сортировки

Используйте 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/:имякласса/:id/:extendName ПОМЕЩАТЬ Установить объект расширения
/1.0/:имякласса/:id/:extendName ПОЧТА Создать объект расширения
/1.0/:имякласса/:id/:extendName/:rid ПОЛУЧАТЬ Чтение объекта расширения
/1.0/:имякласса/:id/:extendName/:rid ПОМЕЩАТЬ Изменить объект расширения
/1.0/:имякласса/:id/:extendName/:rid УДАЛИТЬ Удалить расширенный объект
/1.0/:имякласса/:id/:extendName ПОЛУЧАТЬ Запросить расширенный список объектов

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

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

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

В вызове в теле нужно указать идентификатор кота.

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

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

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 модели. например:

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: user id, user roleи *, idкоторые представляют конкретного пользователя, roleпредставляют пользователей с определенной ролью и *представляют всех пользователей:

основная часть описывать приоритет
ИДЕНТИФИКАТОР конкретный идентификатор пользователя 1
роль Имя группы пользователей 2
* Все 3

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

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

Разрешения

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

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

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

Например, в приведенном выше примере, если вам нужно установить 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сохранении в файл вы получите изображение, подобное следующему: диаграмма