{"id":17198,"library":"database-proxy","title":"Database Proxy with Access Control","description":"database-proxy is a core component within the Laf serverless ecosystem, designed to function as a 'super API' that allows client applications to securely and directly interact with databases (like MongoDB, with future support for MySQL as indicated by keywords) via HTTP. It enables frontend developers to perform database operations without needing a dedicated backend API layer for common CRUD actions. The security and access patterns are enforced through a set of configurable Access Control List (ACL) rules. Currently, the package is in active beta development, with version `1.0.0-beta.14` being the most recent significant release. Releases are frequent, indicating rapid development and feature iteration. Its key differentiator is simplifying backend development by shifting database access control to the proxy layer, significantly reducing the boilerplate traditionally associated with data APIs in BaaS and serverless architectures.","status":"active","version":"1.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/labring/laf","tags":["javascript","BaaS","cloud","mongo","mysql","acl","serverless"],"install":[{"cmd":"npm install database-proxy","lang":"bash","label":"npm"},{"cmd":"yarn add database-proxy","lang":"bash","label":"yarn"},{"cmd":"pnpm add database-proxy","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for MongoDB database connectivity and operations as demonstrated in the server-side integration example.","package":"mongodb","optional":false}],"imports":[{"note":"This package is explicitly CommonJS (`\"type\": \"commonjs\"`) and does not support ESM imports directly. Use `require()`.","wrong":"import { Proxy } from 'database-proxy'","symbol":"Proxy","correct":"const { Proxy } = require('database-proxy')"},{"note":"MongoAccessor is a named export for database interaction. Ensure correct destructuring and CommonJS syntax.","wrong":"import MongoAccessor from 'database-proxy'","symbol":"MongoAccessor","correct":"const { MongoAccessor } = require('database-proxy')"},{"note":"Policy is a named export for defining access control rules. Destructure it directly for clarity.","wrong":"const Policy = require('database-proxy').Policy","symbol":"Policy","correct":"const { Policy } = require('database-proxy')"}],"quickstart":{"code":"const express = require('express');\nconst { Proxy, MongoAccessor, Policy } = require('database-proxy');\nconst { MongoClient } = require('mongodb');\n\nconst app = express();\napp.use(express.json());\n\n// Dummy function for token parsing (replace with actual implementation)\nfunction parseToken(authorizationHeader) {\n  // In a real application, this would validate a JWT and extract user info\n  if (authorizationHeader && authorizationHeader.startsWith('Bearer ')) {\n    const token = authorizationHeader.substring(7);\n    // For demonstration, let's assume a valid token means uid is 'testuser'\n    // In production, decode and verify the token properly.\n    return { uid: 'testuser', admin: true }; // Example: always admin for demo\n  }\n  return { uid: null, admin: false };\n}\n\n// Design the access control policy rules\nconst rules = {\n  categories: {\n    \"read\": true,\n    \"update\": \"$admin === true\", // Only admin can update\n    \"add\": \"$admin === true\",    // Only admin can add\n    \"remove\": \"$admin === true\"\n  },\n  articles: {\n    \"read\": true,\n    \"update\": \"$userid && $userid === query.createdBy\",\n    \"add\": \"$userid && data.createdBy === $userid\",\n    \"remove\": \"$userid === query.createdBy || $admin === true\"\n  }\n};\n\nconst mongoUri = process.env.MONGO_URI ?? 'mongodb://localhost:27017';\nconst client = new MongoClient(mongoUri);\n\nasync function setupDatabaseProxy() {\n  try {\n    await client.connect();\n    console.log('Connected to MongoDB');\n\n    const accessor = new MongoAccessor(client);\n    const policy = new Policy(accessor);\n    policy.load(rules);\n\n    const proxy = new Proxy(accessor, policy);\n\n    app.post('/proxy', async (req, res) => {\n      const { uid, admin } = parseToken(req.headers['authorization']);\n\n      const injections = {\n        uid: uid,\n        admin: admin\n      };\n\n      const params = proxy.parseParams(req.body);\n\n      const result = await proxy.validate(params, injections);\n      if (result.errors) {\n        return res.status(403).send({\n          code: 1,\n          error: result.errors\n        });\n      }\n\n      const data = await proxy.execute(params);\n      return res.send({\n        code: 0,\n        data\n      });\n    });\n\n    const port = 8080;\n    app.listen(port, () => console.log(`Database Proxy listening on http://localhost:${port}/proxy`));\n\n  } catch (error) {\n    console.error('Failed to connect to MongoDB or start server:', error);\n    process.exit(1);\n  }\n}\n\nsetupDatabaseProxy();\n","lang":"javascript","description":"Sets up an Express.js server to expose a secure HTTP endpoint for MongoDB operations using `database-proxy`. It demonstrates how to configure access control rules with `Policy`, inject user context (like `uid` and `admin` status), and handle incoming client database requests, ensuring all operations comply with predefined security policies. This example assumes a MongoDB instance is running locally or accessible via `MONGO_URI`."},"warnings":[{"fix":"Upgrade your Laf deployment, or specifically the `database-proxy` package, to `v1.0.0-beta.14` or later.","message":"A critical security vulnerability (CVE-2023-48225) was fixed in `v1.0.0-beta.14`. All private deployments running older versions of Laf (which includes this package) are strongly advised to update immediately to mitigate potential risks.","severity":"breaking","affected_versions":"<1.0.0-beta.14"},{"fix":"Always use `require()` for importing `database-proxy` and its components in your server-side code.","message":"The `database-proxy` package is designed for CommonJS environments, as indicated by its `package.json` configuration. Attempting to use ES module `import` syntax will result in runtime errors.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Thoroughly design and test your ACL rules. Ensure user identities (`uid`, `admin`, etc.) are securely extracted from authenticated requests and correctly injected into the proxy's validation context.","message":"The effectiveness of the database proxy relies entirely on robust Access Control List (ACL) policies and secure handling of user identity injections. Inadequate or insecure policies can expose your database to unauthorized access or data manipulation.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Change your import statements from `import { Proxy } from 'database-proxy'` to `const { Proxy } = require('database-proxy')`.","cause":"Attempting to use ES module `import` syntax for a CommonJS package.","error":"TypeError: (0 , database_proxy_1.Proxy) is not a constructor"},{"fix":"Ensure your MongoDB connection string (`MONGO_URI`) is correctly formatted, e.g., `mongodb://localhost:27017` or `mongodb+srv://user:pass@cluster.mongodb.net/`.","cause":"An incorrect MongoDB connection string format or attempting to pass connection options in an incompatible way to `MongoClient`.","error":"Error: MongoParseError: options is not a function"},{"fix":"Review your `rules` configuration for the affected collection and the `injections` provided to `proxy.validate()`. Ensure the user's role and data context satisfy the policy conditions for the requested action.","cause":"The incoming database operation (read, update, add, remove) violates the defined `Policy` rules for the collection or document, given the injected user context.","error":"code: 1, error: 'Access denied: operation not permitted by policy'"}],"ecosystem":"npm","meta_description":null}