# database-proxy

> Through a set of access control rules configuration database access to realize the client directly access the database via HTTP.

Latest version **1.0.0** (published 2024-04-01) · ISC license · 0 weekly downloads

## Install

```sh
npm install database-proxy
pnpm add database-proxy
yarn add database-proxy
bun add database-proxy
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 1.0.0 |
| Published | 2024-04-01 |
| First published | 2021-10-06 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 4 |
| Unpacked size | 170.6 KB |
| Known vulnerabilities | 0 (+7 in 1 direct dependencies) |
| Install scripts | no |
| GitHub stars | 7544 |
| Author | maslow |
| Maintainers | maslow |
| Keywords | BaaS, cloud, mongo, mysql, acl, serverless |

## Links

- npm: https://www.npmjs.com/package/database-proxy
- Repository: https://github.com/labring/laf
- Homepage: https://github.com/labring/laf#readme
- Issues: https://github.com/labring/laf/issues
- npm.io page: https://npm.io/package/database-proxy

## Dependencies (4)

- [mysql2](https://npm.io/package/mysql2.md) ^2.2.5
- [mongodb](https://npm.io/package/mongodb.md) ^5.9.2
- [validator](https://npm.io/package/validator.md) ^13.7.0
- [database-ql](https://npm.io/package/database-ql.md) ^1.0.0

## Alternatives

- [angular-pipes](https://npm.io/package/angular-pipes.md) — 5.6K weekly downloads
- [@ng-web-apis/midi](https://npm.io/package/@ng-web-apis/midi.md) — 2.6K weekly downloads
- [happn-3](https://npm.io/package/happn-3.md) — 1.6K weekly downloads
- [@opensip-cli/lang-go](https://npm.io/package/@opensip-cli/lang-go.md) — 1.2K weekly downloads
- [@temporal-architect/claude-plugin](https://npm.io/package/@temporal-architect/claude-plugin.md) — 335 weekly downloads

## Recent versions

- 1.0.0 (latest) — 2024-04-01
- 1.0.0-beta.14-patch0 (preview) — 2023-12-21
- 1.0.0-beta.14 — 2023-12-19
- 1.0.0-beta.12-pr0 — 2023-12-14
- 1.0.0-beta.12 — 2023-10-31
- 1.0.0-beta.2 — 2023-02-24
- 0.8.2 — 2022-06-06
- 0.8.0-alpha.9 — 2022-05-15
- 0.7.10 — 2022-02-09
- 0.7.1 — 2022-01-17
- 0.7.0 — 2021-12-28
- 0.6.4 — 2021-11-01
- 0.6.3 — 2021-10-23
- 0.6.2 — 2021-10-20
- 0.6.1 — 2021-10-20
- … 9 more at https://npm.io/package/database-proxy/versions

## README

## 介绍

    `database-proxy` 是一个「超级API」，一个 API 替代服务端 90% 的传统 APIs。

    通过一套「访问控制规则」配置数据库访问，让前端开发者“安全直连”数据库，再也不需要和服务端对接口了！

    客户端使用 `laf-client-sdk` ，像在服务端操作数据库那样，在客户端直接读写相应的数据即可。

## 使用

```sh
    npm install database-proxy
```

### 服务端代码示例

```js
const app = require('express')()
const { Proxy, MongoAccessor, Policy } = require('database-proxy')
const { MongoClient } = require('mongodb')

app.use(express.json())

// design the access control policy rules
const rules = {
    categories: {
        "read": true,
        "update": "!uid",
        "add": "!uid",
        "remove": "!uid"
    }
}

const client = new MongoClient('mongodb://localhost:27017')
client.connect()

// create an accessor
const accessor = new MongoAccessor(client)


// create a policy
const policy = new Policy(accessor)
policy.load(rules)

// create an proxy
const proxy = new Proxy(accessor, policy)

app.post('/proxy', async (req, res) => {
  const { uid } = parseToken(req.headers['authorization'])

  const injections = {
    uid: uid
  }

  // parse params
  const params = proxy.parseParams(req.body)

  // validate query
  const result = await proxy.validate(params, injections)
  if (result.errors) {
    return res.send({
      code: 1,
      error: result.errors
    })
  }

  // execute query
  const data = await proxy.execute(params)
  return res.send({
    code: 0,
    data
  })
})

app.listen(8080, () => console.log('listening on 8080'))
```

### 客户端使用

```sh
    npm install laf-client-sdk
```

```js
const cloud = require('laf-client-sdk').init({
    dbProxyUrl: 'http://localhost:8080/proxy',
    getAccessToken: () => localStorage.getItem('access_token')
})

const db = cloud.database()

// 查询文档
const res = await db.collection('categories').get()

// 条件查询
const res = await db.collection('articles')
    .where({status: 'published'})
    .orderBy({createdAt: 'asc'})
    .offset(0)
    .limit(20)
    .get()

// 更新
const res = await db.collection('articles')
    .doc('the-doc-id').update({
        title: 'new-title'
    })
```

更多使用参考[客户端使用文档](./packages/laf-client-sdk/README.md)

### 数据访问安全规则示例

#### 简单示例 1：简单博客

```json
{
    "categories": {
        "read": true,
        "update": "$admin === true",
        "add": "$admin === true",
        "remove": "$admin === true"
    },
    "articles": {
        "read": true,
        "update": "$admin === true",
        "add": "$admin === true",
        "remove": "$admin === true"
    }
}
```

#### 简单示例 2：多用户博客

```json
{
    "articles": {
        "read": true,
        "update": "$userid && $userid === query.createdBy",
        "add": "$userid && data.createdBy === $userid",
        "remove": "$userid === query.createBy || $admin === true"
    }
}
```

#### 复杂示例 1： 数据验证

```json
{
    "articles": {
        "add": {
            "condition": "$userid && data.createdBy === $userid"
        },
        "remove": "$userid === query.createBy || $admin === true",
        "$schema": {
            "title": {"length": [1, 64], "required": true},
            "content": {"length": [1, 4096]},
            "like": { "number": [0,], "default": 0}
        }
    }
}
```

#### 复杂示例 2：更高级的数据验证

> 场景介绍： 用户之间站内消息表访问规则

```json
{
    "messages": {
        "read": "$userid && ($userid === query.receiver || $userid === query.sender)",
        "update": {
            "condition": "$userid && $userid === query.receiver",
            "data": {
                "read": {"in": [true]}
            }
        },
        "add": {
            "condition": "$userid && $userid === data.sender",
             "data": {
                "read": {"in": [false]}
            }
        },
        "remove": false,
        "$schema": {
            "content": {"length": [1, 20480], "required": true},
            "receiver": {"exists": "/users/id"},
            "read": { "in": [true, false], "default": false }
        }
    }
}
```

## 运行测试

安装依赖

```sh
    npm i
```

### 单元测试

```sh
    npx mocha tests/units/*.test.js
```

### 数据库访问测试
#### Mongo

使用 Docker 启动个测试数据库，等待mongo 启动成功

```sh
    docker pull mongo
    docker run --rm -p 27018:27017 --name mongotest -d mongo
```

执行测试用例

```sh
    npx mocha tests/mongo_db/*.test.js
```

停止&删除 Mongo 实例

```sh
    docker rm -f mongotest
```

#### MySQL

使用 Docker 启动个测试数据库，等待mongo 启动成功

```sh
    docker pull mysql
    docker run --name mysqltest -e MYSQL_ROOT_PASSWORD=kissme -e MYSQL_DATABASE=testdb -d -p 3306:3306 mysql
```

手动创建测试使用的数据表：
```sql
create table IF NOT EXISTS categories (
  id int not null auto_increment,
  name varchar(64) not null, 
  created_at int, 
  primary key(id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

create table IF NOT EXISTS articles (
  id int not null auto_increment,
  title varchar(64) not null, 
  category_id int,
  content text,
  created_at int, 
  updated_at int,
  created_by int,
  primary key(id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

执行测试用例

```sh
    npx mocha tests/mysql_db/*.test.js
```

停止&删除 Mongo 实例

```sh
    docker rm -f mysqltest
```

### 执行所有测试用例

> 请确保已经运行 mongo 和 mysql 测试的实例；

```sh
npx mocha tests/**/*.test.js
```

---
_Source: https://npm.io/package/database-proxy · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
