better-auth-studio 1.1.3-beta.47 → 1.1.3-beta.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -10
- package/dist/adapters/express.js +1 -0
- package/dist/core/handler.js +19 -0
- package/dist/public/assets/{main-B5zPj0kP.js → main-B-gWWl9A.js} +3 -3
- package/dist/public/assets/{main-BboBzuv8.css → main-C-R_HO98.css} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/routes/api-router.d.ts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/routes.js +48 -0
- package/dist/types/handler.d.ts +10 -0
- package/dist/utils/access-rules.d.ts +19 -0
- package/dist/utils/access-rules.js +126 -0
- package/dist/utils/html-injector.d.ts +1 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -187,12 +187,14 @@ pnpx better-auth-studio start [options]
|
|
|
187
187
|
|
|
188
188
|
**Options:**
|
|
189
189
|
|
|
190
|
-
- `--port <number>` - Specify port (default:
|
|
190
|
+
- `--port <number>` - Specify port (default: 3002)
|
|
191
191
|
- `--host <string>` - Specify host (default: localhost)
|
|
192
192
|
- `--no-open` - Don't automatically open browser
|
|
193
193
|
- `--config <path>` - Path to auth config file (default: auto-detect)
|
|
194
194
|
- `--watch` - Watch for changes in auth config file and reload server automatically
|
|
195
195
|
|
|
196
|
+
`3002` is just the standalone Studio default so it does not clash with apps that already use `3000`. You can run Studio on `3000`, `4000`, or any other free port.
|
|
197
|
+
|
|
196
198
|
**Examples:**
|
|
197
199
|
|
|
198
200
|
```bash
|
|
@@ -270,6 +272,62 @@ pnpm add better-auth-studio
|
|
|
270
272
|
|
|
271
273
|
> **Note:** The CLI usage (standalone studio) can be installed as a dev dependency, but self-hosting requires it in `dependencies` for production deployments.
|
|
272
274
|
|
|
275
|
+
### Docker (Standalone Self-Host)
|
|
276
|
+
|
|
277
|
+
If you want to run Better Auth Studio in its own container, this repository includes a Docker setup for the standalone CLI server.
|
|
278
|
+
|
|
279
|
+
This mode is useful when:
|
|
280
|
+
|
|
281
|
+
- you want a separate admin container
|
|
282
|
+
- your Better Auth app already lives in its own repository
|
|
283
|
+
- you want Docker-managed `node_modules` and package-manager cache volumes
|
|
284
|
+
|
|
285
|
+
> **Important:** The standalone container still needs your Better Auth project mounted into it, because Studio loads your real `auth.ts` and `studio.config.*` files at runtime.
|
|
286
|
+
|
|
287
|
+
Build the image from this repository:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
docker build -t better-auth-studio:self-host .
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Run it with Docker Compose:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
HOST_PROJECT_PATH=/absolute/path/to/your-better-auth-project \
|
|
297
|
+
CONFIG_PATH=./auth.ts \
|
|
298
|
+
docker compose -f docker/compose.yml up --build
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
If your auth config is not at the project root, pass it explicitly:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
HOST_PROJECT_PATH=/absolute/path/to/your-better-auth-project \
|
|
305
|
+
CONFIG_PATH=./src/lib/auth.ts \
|
|
306
|
+
docker compose -f docker/compose.yml up --build
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
If you already used the older filename, `docker/docker-compose.self-host.yml` still works too.
|
|
310
|
+
|
|
311
|
+
What the container does:
|
|
312
|
+
|
|
313
|
+
- mounts your Better Auth project into `/workspace`
|
|
314
|
+
- installs project dependencies into Docker volumes on first boot
|
|
315
|
+
- starts `better-auth-studio start --host 0.0.0.0 --port 3002 --no-open`
|
|
316
|
+
|
|
317
|
+
Useful environment variables:
|
|
318
|
+
|
|
319
|
+
- `HOST_PROJECT_PATH` - absolute path to your Better Auth project on the host machine
|
|
320
|
+
- `CONFIG_PATH` - optional auth config path inside the mounted project, for example `./src/lib/auth.ts`
|
|
321
|
+
- `PORT` - studio port, defaults to `3002`
|
|
322
|
+
- `WATCH` - set to `true` to enable watch mode
|
|
323
|
+
- `AUTO_INSTALL` - set to `false` if your container/project already has dependencies installed
|
|
324
|
+
- `PROJECT_INSTALL_CMD` - optional custom install command for non-standard setups
|
|
325
|
+
- `GEO_DB_PATH` - optional GeoLite database path inside the mounted project
|
|
326
|
+
|
|
327
|
+
If you change the Studio port, make sure your Better Auth config also trusts that origin when needed. The examples usually include both `http://localhost:3000` and `http://localhost:3002` for that reason.
|
|
328
|
+
|
|
329
|
+
If you already embed Studio in your server with the framework adapters below, that remains the recommended production setup. The Docker flow is mainly for running the standalone Studio server in a containerized environment.
|
|
330
|
+
|
|
273
331
|
### Setup
|
|
274
332
|
|
|
275
333
|
**Step 1: Initialize configuration**
|
|
@@ -294,6 +352,8 @@ const config: StudioConfig = {
|
|
|
294
352
|
access: {
|
|
295
353
|
roles: ["admin"],
|
|
296
354
|
allowEmails: ["admin@example.com"],
|
|
355
|
+
allowIpAddresses: ["127.0.0.1", "::1", "192.168.*"],
|
|
356
|
+
blockIpAddresses: ["203.0.113.45"],
|
|
297
357
|
},
|
|
298
358
|
};
|
|
299
359
|
|
|
@@ -339,15 +399,17 @@ Access at `http://localhost:3000/api/studio`
|
|
|
339
399
|
|
|
340
400
|
### Configuration Options
|
|
341
401
|
|
|
342
|
-
| Option
|
|
343
|
-
|
|
|
344
|
-
| `auth`
|
|
345
|
-
| `basePath`
|
|
346
|
-
| `access.allowEmails`
|
|
347
|
-
| `access.roles`
|
|
348
|
-
| `
|
|
349
|
-
| `
|
|
350
|
-
| `
|
|
402
|
+
| Option | Required | Description |
|
|
403
|
+
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
404
|
+
| `auth` | Yes | Your Better Auth instance |
|
|
405
|
+
| `basePath` | Yes | URL path where studio is mounted |
|
|
406
|
+
| `access.allowEmails` | No | Array of admin email addresses |
|
|
407
|
+
| `access.roles` | No | Array of allowed user roles |
|
|
408
|
+
| `access.allowIpAddresses` | No | IP allowlist for Studio requests. Supports exact IPs and wildcard patterns (example: `192.168.*`) |
|
|
409
|
+
| `access.blockIpAddresses` | No | IP blocklist for Studio requests. Supports exact IPs and wildcard patterns |
|
|
410
|
+
| `ipAddress` | No | IP geolocation for Events/Sessions: `provider` ("ipinfo" \| "ipapi"), `apiToken`, `baseUrl`, optional `endpoint` (ipinfo: "lite" \| "lookup") |
|
|
411
|
+
| `lastSeenAt` | No | Enable last-seen tracking: `{ enabled: true, columnName?: string }` |
|
|
412
|
+
| `metadata` | No | Custom branding (title, theme) |
|
|
351
413
|
|
|
352
414
|
## 📝 Development
|
|
353
415
|
|
package/dist/adapters/express.js
CHANGED
package/dist/core/handler.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createClickHouseProvider, createHttpProvider, createNodeSqliteProvider,
|
|
|
5
5
|
import { initializeEventIngestion, isEventIngestionInitialized } from "../utils/event-ingestion.js";
|
|
6
6
|
import { injectEventHooks, injectLastSeenAtHooks } from "../utils/hook-injector.js";
|
|
7
7
|
import { serveIndexHtml as getIndexHtml } from "../utils/html-injector.js";
|
|
8
|
+
import { evaluateRequestAccess } from "../utils/access-rules.js";
|
|
8
9
|
import { decryptSession, isSessionValid, STUDIO_COOKIE_NAME } from "../utils/session.js";
|
|
9
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
11
|
const __dirname = dirname(__filename);
|
|
@@ -132,6 +133,23 @@ export async function handleStudioRequest(request, config) {
|
|
|
132
133
|
if (path === "" || path === "/") {
|
|
133
134
|
path = "/";
|
|
134
135
|
}
|
|
136
|
+
if (isSelfHosted) {
|
|
137
|
+
const accessDecision = evaluateRequestAccess({
|
|
138
|
+
accessConfig: config.access,
|
|
139
|
+
path,
|
|
140
|
+
method: request.method,
|
|
141
|
+
headers: request.headers,
|
|
142
|
+
ip: request.ip,
|
|
143
|
+
});
|
|
144
|
+
if (!accessDecision.allowed) {
|
|
145
|
+
return jsonResponse(403, {
|
|
146
|
+
success: false,
|
|
147
|
+
message: accessDecision.message,
|
|
148
|
+
reason: accessDecision.reason,
|
|
149
|
+
...(accessDecision.ipAddress ? { ipAddress: accessDecision.ipAddress } : {}),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
135
153
|
if (path.startsWith("/assets/") ||
|
|
136
154
|
path === "/vite.svg" ||
|
|
137
155
|
path === "/favicon.svg" ||
|
|
@@ -262,6 +280,7 @@ async function handleApiRoute(request, path, config) {
|
|
|
262
280
|
path: path,
|
|
263
281
|
method: request.method,
|
|
264
282
|
headers: request.headers,
|
|
283
|
+
ip: request.ip,
|
|
265
284
|
body: request.body,
|
|
266
285
|
auth: config.auth,
|
|
267
286
|
basePath: config.basePath || "/api/studio",
|