멋진 커뮤니티 모듈

fib-app

fibjs 애플리케이션 기본 API 프레임 워크

설치

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 형식이어야하며 HTTP 헤더의 Content-Type은 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 } ]

특수 분야

오브젝트 데이터에는 특별한 의미를 지닌 4 개의 필드가 있으며 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 가져 오기 쿼리 개체 목록

새 개체 만들기

새 객체를 생성하려면 객체 자체를 포함해야하는 클래스의 URL로 POST 요청을 보내야합니다. 예를 들어 위에서 언급 한대로 개체를 만들려면

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이고 응답 본문은 새 개체의 objectId 및 createdAt 타임 스탬프를 포함하는 JSON 개체입니다.

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

개체 읽기

객체를 생성 할 때 반환 된 헤더의 위치에 GET 요청을 전송하여 해당 내용을 가져올 수 있습니다. 예를 들어 위에서 만든 객체를 가져 오려면 :

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

반환 된 본문은 모든 사용자 제공 필드와 createdAt , updatedAtid 필드를 포함하는 JSON 객체입니다.

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

field returns keys 를 설정하면 사용자 정의 된 컨텐츠가 리턴 될 수 있으며 컨텐츠에 대한 keys , 세그먼트 화 필드 이름 문자열 :

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

반환 :

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

개체 수정

객체의 기존 데이터를 변경하려면 객체의 해당 URL로 PUT 요청을 보낼 수 있습니다. 지정하지 않은 키는 변경되지 않으므로 객체 데이터의 하위 집합 만 업데이트 할 수 있습니다. 예를 들어 객체의 연령 필드를 변경해 보겠습니다.

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

반환 된 JSON 개체에는 업데이트가 발생한 시간을 나타내는 updatedAtid 필드가 포함됩니다.

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

개체 삭제

객체를 삭제하려면 다음과 같이 지정된 객체의 URL로 DELETE 요청을 보낼 수 있습니다.

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

쿼리 개체 목록

클래스의 URL에 GET 요청을 보내면 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

nameage 두 필드 만 반환하도록 지정합니다.

필터 조건

쿼리 개체는 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 의 값은 urlencode 뒤의 JSON 문자열이며 내용은 {"name":"tom"}

정확히 소정 값과 일치하는 것 외에도 where 또한 포함 같이 비교 방법을 지원한다. where 매개 변수는 다음 옵션을 지원합니다.

조작 견본
eq 같은 { "name": { "eq": "tom"}} 또는 { "name": "tom"}
ne 같지 않음 { "이름": { "ne": "tom"}}
gt 보다 { "age": { "gt": "24"}}
gte 크거나 같음 { "age": { "gte": "24"}}
lt 이하 { "age": { "lt": "24"}}
lte 작거나 같음 { "age": { "lte": "24"}}
처럼 퍼지 쿼리 { "이름": { "like": "% m"}}
좋아하지 않는 퍼지 쿼리 { "name": { "not_like": "% m"}}
중에서 간격 비교 { "age": { "between": [22,25]}}
not_between 간격 비교 { "age": { "not_between": [22,25]}}
낱낱이 세다 { "이름": { "in": [ "tom", "lily"]}}
not_in 낱낱이 세다 { "이름": { "not_in": [ "tom", "lily"]}}
또는 OR 작업 { "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

이때 반환 된 결과에는 각각 total 및 result가 포함 된 countresults 필드 두 개가 포함됩니다.

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

확장 개체 만들기

orm을 통해 hasOne 및 hasMany를 정의하면 다음과 같이 객체 간의 관계를 정의하고 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 가져 오기 확장 개체 목록 쿼리

확장 개체 설정

확장 된 개체를 설정하는 것은 두 개의 독립적 인 개체 간의 연결을 설정하는 것입니다. 예를 들어 Tom은 cat이라는 애완 동물을 입양했으며 다음 작업을 통해 수행 할 수 있습니다.

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

호출시 cat의 id를 본문에 지정해야합니다.

확장 개체 만들기

확장 개체를 직접 생성하여 개체를 생성하는 동안 개체 간의 연결을 설정할 수 있습니다. 예 :

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

cat이라는 이름의 애완 동물이 생성되고 tom과의 관계가 설정됩니다.

확장 개체 읽기

확장 된 개체를 읽는 것은 기본 개체를 읽는 것과 매우 유사하며 키 옵션도 지원합니다.

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 주제 설명에는 user id , user role* 세 가지 유형이 있습니다. id 는 특정 사용자, role 은 특정 역할을 가진 사용자, * 는 모든 사용자를 나타냅니다.

본체 기술 우선 순위
신분증 특정 사용자의 ID 1
역할 사용자 그룹 이름 2
* 모두

권한을 검토 한 결과, 먼저 일치 id 지정되지 않은 경우 권한이 사용자의 일치, 해당 role 여전히 지정한 경우, 권한을 해당, 그것은 여부에 보이는 * 경우 권한, * 도 지정하지 않으면 권한이 없습니다.

예를 들어, 위의 권한 구성은 user 사용자 그룹이 읽을 수 user 지정하고 사용자 57fbbdb0a2400000 은 모든 권한을 가지며 다른 사용자는 권한이 없습니다.

권위

ACL은 API 동작에 따라 5 가지 유형의 권한을 분류합니다.

권위 기술 허용되는 유형
창조하다 개체 만들기 참 / 거짓 / 배열
읽다 개체 읽기 참 / 거짓 / 배열
쓰다 개체 수정 참 / 거짓 / 배열
지우다 개체 삭제 허위 사실
찾기 쿼리 개체 목록 허위 사실
* 모든 권한 일치 참 / 거짓 / 배열

권한은 액세스를 허용하려면 true 로, 액세스를 금지하려면 false 로, 지정된 필드에만 액세스를 허용하려면 array 로 설정됩니다. deletefindarray 허용하지 않습니다. array 가 설정되어 있으면 true 로 간주됩니다. 지정된 권한이 없으면 동일한 프린시 펄 아래의 * 권한과 일치합니다. 존재하지 않는 경우 다음 우선 순위로 주제를 다시 쿼리하십시오.

예를 들어 사용자가 설정해야하는 경우, 위의 예에서 user 경우에만 읽기 허용 titledetail , 그리고 다른 사람들이 읽을 수있는 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); };

이 정의에서 누구나 개인 정보의 namesex 확인할 수 있으며, 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 형식 클래스 다이어그램을 그리고 파일에 저장하여 다음과 유사한 이미지를 얻을 수 있습니다. 도표