@sudobility/shapeshyft_service 1.0.0
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/CLAUDE.md +35 -0
- package/README.md +17 -0
- package/dist/context.d.ts +62 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +55 -0
- package/dist/context.js.map +1 -0
- package/dist/contracts.d.ts +110 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +7 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-key.d.ts +22 -0
- package/dist/lib/api-key.d.ts.map +1 -0
- package/dist/lib/api-key.js +87 -0
- package/dist/lib/api-key.js.map +1 -0
- package/dist/lib/encryption.d.ts +22 -0
- package/dist/lib/encryption.d.ts.map +1 -0
- package/dist/lib/encryption.js +41 -0
- package/dist/lib/encryption.js.map +1 -0
- package/dist/lib/entity-api-key.d.ts +21 -0
- package/dist/lib/entity-api-key.d.ts.map +1 -0
- package/dist/lib/entity-api-key.js +54 -0
- package/dist/lib/entity-api-key.js.map +1 -0
- package/dist/lib/entity-helpers.d.ts +90 -0
- package/dist/lib/entity-helpers.d.ts.map +1 -0
- package/dist/lib/entity-helpers.js +136 -0
- package/dist/lib/entity-helpers.js.map +1 -0
- package/dist/lib/money.d.ts +7 -0
- package/dist/lib/money.d.ts.map +1 -0
- package/dist/lib/money.js +9 -0
- package/dist/lib/money.js.map +1 -0
- package/dist/lib/public-project.d.ts +14 -0
- package/dist/lib/public-project.d.ts.map +1 -0
- package/dist/lib/public-project.js +17 -0
- package/dist/lib/public-project.js.map +1 -0
- package/dist/lib/user-api-key-cache.d.ts +35 -0
- package/dist/lib/user-api-key-cache.d.ts.map +1 -0
- package/dist/lib/user-api-key-cache.js +99 -0
- package/dist/lib/user-api-key-cache.js.map +1 -0
- package/dist/lib/user-api-key.d.ts +46 -0
- package/dist/lib/user-api-key.d.ts.map +1 -0
- package/dist/lib/user-api-key.js +102 -0
- package/dist/lib/user-api-key.js.map +1 -0
- package/dist/middleware/firebaseAuth.d.ts +34 -0
- package/dist/middleware/firebaseAuth.d.ts.map +1 -0
- package/dist/middleware/firebaseAuth.js +133 -0
- package/dist/middleware/firebaseAuth.js.map +1 -0
- package/dist/middleware/rateLimit.d.ts +29 -0
- package/dist/middleware/rateLimit.d.ts.map +1 -0
- package/dist/middleware/rateLimit.js +85 -0
- package/dist/middleware/rateLimit.js.map +1 -0
- package/dist/middleware/subscription.d.ts +8 -0
- package/dist/middleware/subscription.d.ts.map +1 -0
- package/dist/middleware/subscription.js +19 -0
- package/dist/middleware/subscription.js.map +1 -0
- package/dist/routes/ai.d.ts +10 -0
- package/dist/routes/ai.d.ts.map +1 -0
- package/dist/routes/ai.js +698 -0
- package/dist/routes/ai.js.map +1 -0
- package/dist/routes/analytics.d.ts +9 -0
- package/dist/routes/analytics.d.ts.map +1 -0
- package/dist/routes/analytics.js +192 -0
- package/dist/routes/analytics.js.map +1 -0
- package/dist/routes/endpoints.d.ts +10 -0
- package/dist/routes/endpoints.d.ts.map +1 -0
- package/dist/routes/endpoints.js +255 -0
- package/dist/routes/endpoints.js.map +1 -0
- package/dist/routes/entities.d.ts +15 -0
- package/dist/routes/entities.d.ts.map +1 -0
- package/dist/routes/entities.js +332 -0
- package/dist/routes/entities.js.map +1 -0
- package/dist/routes/entity-api-keys.d.ts +17 -0
- package/dist/routes/entity-api-keys.d.ts.map +1 -0
- package/dist/routes/entity-api-keys.js +142 -0
- package/dist/routes/entity-api-keys.js.map +1 -0
- package/dist/routes/invitations.d.ts +15 -0
- package/dist/routes/invitations.d.ts.map +1 -0
- package/dist/routes/invitations.js +58 -0
- package/dist/routes/invitations.js.map +1 -0
- package/dist/routes/projects.d.ts +9 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +241 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/providers.d.ts +9 -0
- package/dist/routes/providers.d.ts.map +1 -0
- package/dist/routes/providers.js +89 -0
- package/dist/routes/providers.js.map +1 -0
- package/dist/routes/ratelimits.d.ts +9 -0
- package/dist/routes/ratelimits.d.ts.map +1 -0
- package/dist/routes/ratelimits.js +171 -0
- package/dist/routes/ratelimits.js.map +1 -0
- package/dist/routes/settings.d.ts +9 -0
- package/dist/routes/settings.d.ts.map +1 -0
- package/dist/routes/settings.js +138 -0
- package/dist/routes/settings.js.map +1 -0
- package/dist/routes/storage.d.ts +9 -0
- package/dist/routes/storage.d.ts.map +1 -0
- package/dist/routes/storage.js +180 -0
- package/dist/routes/storage.js.map +1 -0
- package/dist/routes/user-api-keys.d.ts +14 -0
- package/dist/routes/user-api-keys.d.ts.map +1 -0
- package/dist/routes/user-api-keys.js +237 -0
- package/dist/routes/user-api-keys.js.map +1 -0
- package/dist/routes/users.d.ts +7 -0
- package/dist/routes/users.d.ts.map +1 -0
- package/dist/routes/users.js +102 -0
- package/dist/routes/users.js.map +1 -0
- package/dist/schema/init.d.ts +12 -0
- package/dist/schema/init.d.ts.map +1 -0
- package/dist/schema/init.js +404 -0
- package/dist/schema/init.js.map +1 -0
- package/dist/schema/tables.d.ts +2110 -0
- package/dist/schema/tables.d.ts.map +1 -0
- package/dist/schema/tables.js +251 -0
- package/dist/schema/tables.js.map +1 -0
- package/dist/schemas/index.d.ts +671 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +299 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/service.d.ts +41 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +70 -0
- package/dist/service.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview User settings routes
|
|
3
|
+
* @description Manages per-user settings including organization name and path.
|
|
4
|
+
* Uses upsert pattern -- settings are created on first PUT if they don't exist.
|
|
5
|
+
*/
|
|
6
|
+
import { Hono } from "hono";
|
|
7
|
+
import { zValidator } from "@hono/zod-validator";
|
|
8
|
+
import { eq } from "drizzle-orm";
|
|
9
|
+
import { settingsUpdateSchema } from "../schemas/index.js";
|
|
10
|
+
import { successResponse, errorResponse, } from "@sudobility/shapeshyft_engine/types";
|
|
11
|
+
export function createSettingsRouter(ctx) {
|
|
12
|
+
const { db } = ctx;
|
|
13
|
+
const { users, userSettings } = ctx.tables;
|
|
14
|
+
const settingsRouter = new Hono();
|
|
15
|
+
/**
|
|
16
|
+
* Helper to get or create user by Firebase UID
|
|
17
|
+
*/
|
|
18
|
+
async function getOrCreateUser(firebaseUid, email) {
|
|
19
|
+
const existing = await db
|
|
20
|
+
.select()
|
|
21
|
+
.from(users)
|
|
22
|
+
.where(eq(users.firebase_uid, firebaseUid));
|
|
23
|
+
if (existing.length > 0) {
|
|
24
|
+
return existing[0];
|
|
25
|
+
}
|
|
26
|
+
const created = await db
|
|
27
|
+
.insert(users)
|
|
28
|
+
.values({
|
|
29
|
+
firebase_uid: firebaseUid,
|
|
30
|
+
email: email ?? null,
|
|
31
|
+
})
|
|
32
|
+
.returning();
|
|
33
|
+
return created[0];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate default organization path from firebase UID
|
|
37
|
+
* Uses first 8 characters of the UID (without special characters)
|
|
38
|
+
*/
|
|
39
|
+
function generateDefaultOrgPath(firebaseUid) {
|
|
40
|
+
return firebaseUid.replace(/[^a-zA-Z0-9]/g, "").slice(0, 8);
|
|
41
|
+
}
|
|
42
|
+
// GET user settings
|
|
43
|
+
settingsRouter.get("/", async (c) => {
|
|
44
|
+
const authUserId = c.get("userId");
|
|
45
|
+
const authUserEmail = c.get("userEmail");
|
|
46
|
+
const userId = c.req.param("userId");
|
|
47
|
+
if (authUserId !== userId) {
|
|
48
|
+
return c.json(errorResponse("You can only access your own settings"), 403);
|
|
49
|
+
}
|
|
50
|
+
const user = await getOrCreateUser(authUserId, authUserEmail ?? undefined);
|
|
51
|
+
const rows = await db
|
|
52
|
+
.select()
|
|
53
|
+
.from(userSettings)
|
|
54
|
+
.where(eq(userSettings.firebase_uid, user.firebase_uid));
|
|
55
|
+
if (rows.length === 0) {
|
|
56
|
+
// Return default settings with auto-generated org path
|
|
57
|
+
const defaultSettings = {
|
|
58
|
+
id: null,
|
|
59
|
+
firebase_uid: user.firebase_uid,
|
|
60
|
+
organization_name: null,
|
|
61
|
+
organization_path: generateDefaultOrgPath(user.firebase_uid),
|
|
62
|
+
is_default: true,
|
|
63
|
+
created_at: null,
|
|
64
|
+
updated_at: null,
|
|
65
|
+
};
|
|
66
|
+
return c.json(successResponse(defaultSettings));
|
|
67
|
+
}
|
|
68
|
+
const settings = { ...rows[0], is_default: false };
|
|
69
|
+
return c.json(successResponse(settings));
|
|
70
|
+
});
|
|
71
|
+
// PUT create/update settings (upsert)
|
|
72
|
+
settingsRouter.put("/", zValidator("json", settingsUpdateSchema), async (c) => {
|
|
73
|
+
const authUserId = c.get("userId");
|
|
74
|
+
const authUserEmail = c.get("userEmail");
|
|
75
|
+
const userId = c.req.param("userId");
|
|
76
|
+
const body = c.req.valid("json");
|
|
77
|
+
if (authUserId !== userId) {
|
|
78
|
+
return c.json(errorResponse("You can only update your own settings"), 403);
|
|
79
|
+
}
|
|
80
|
+
const user = await getOrCreateUser(authUserId, authUserEmail ?? undefined);
|
|
81
|
+
// Check if settings exist
|
|
82
|
+
const existing = await db
|
|
83
|
+
.select()
|
|
84
|
+
.from(userSettings)
|
|
85
|
+
.where(eq(userSettings.firebase_uid, user.firebase_uid));
|
|
86
|
+
// If changing organization_path, check for duplicates
|
|
87
|
+
if (body.organization_path) {
|
|
88
|
+
const duplicate = await db
|
|
89
|
+
.select()
|
|
90
|
+
.from(userSettings)
|
|
91
|
+
.where(eq(userSettings.organization_path, body.organization_path));
|
|
92
|
+
if (duplicate.length > 0 &&
|
|
93
|
+
(existing.length === 0 ||
|
|
94
|
+
duplicate[0].firebase_uid !== user.firebase_uid)) {
|
|
95
|
+
return c.json(errorResponse("Organization path already taken"), 409);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (existing.length === 0) {
|
|
99
|
+
// Create new settings
|
|
100
|
+
const orgPath = body.organization_path || generateDefaultOrgPath(user.firebase_uid);
|
|
101
|
+
// Double-check the auto-generated path isn't taken
|
|
102
|
+
if (!body.organization_path) {
|
|
103
|
+
const autoPathCheck = await db
|
|
104
|
+
.select()
|
|
105
|
+
.from(userSettings)
|
|
106
|
+
.where(eq(userSettings.organization_path, orgPath));
|
|
107
|
+
if (autoPathCheck.length > 0) {
|
|
108
|
+
return c.json(errorResponse("Auto-generated organization path is taken. Please provide a custom organization_path."), 409);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const rows = await db
|
|
112
|
+
.insert(userSettings)
|
|
113
|
+
.values({
|
|
114
|
+
firebase_uid: user.firebase_uid,
|
|
115
|
+
organization_name: body.organization_name ?? null,
|
|
116
|
+
organization_path: orgPath,
|
|
117
|
+
})
|
|
118
|
+
.returning();
|
|
119
|
+
const created = { ...rows[0], is_default: false };
|
|
120
|
+
return c.json(successResponse(created), 201);
|
|
121
|
+
}
|
|
122
|
+
// Update existing settings
|
|
123
|
+
const current = existing[0];
|
|
124
|
+
const rows = await db
|
|
125
|
+
.update(userSettings)
|
|
126
|
+
.set({
|
|
127
|
+
organization_name: body.organization_name ?? current.organization_name,
|
|
128
|
+
organization_path: body.organization_path ?? current.organization_path,
|
|
129
|
+
updated_at: new Date(),
|
|
130
|
+
})
|
|
131
|
+
.where(eq(userSettings.firebase_uid, user.firebase_uid))
|
|
132
|
+
.returning();
|
|
133
|
+
const updated = { ...rows[0], is_default: false };
|
|
134
|
+
return c.json(successResponse(updated));
|
|
135
|
+
});
|
|
136
|
+
return settingsRouter;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/routes/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Entity cloud storage configuration routes
|
|
3
|
+
* @description Manages GCS/S3 storage configs for entities. Credentials
|
|
4
|
+
* are encrypted at rest using AES-256-CBC. Supports create, update, and delete.
|
|
5
|
+
*/
|
|
6
|
+
import { Hono } from "hono";
|
|
7
|
+
import type { ServiceContext } from "../context.js";
|
|
8
|
+
export declare function createStorageRouter(ctx: ServiceContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
9
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/routes/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAa5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,cAAc,8EAkQtD"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Entity cloud storage configuration routes
|
|
3
|
+
* @description Manages GCS/S3 storage configs for entities. Credentials
|
|
4
|
+
* are encrypted at rest using AES-256-CBC. Supports create, update, and delete.
|
|
5
|
+
*/
|
|
6
|
+
import { Hono } from "hono";
|
|
7
|
+
import { zValidator } from "@hono/zod-validator";
|
|
8
|
+
import { eq } from "drizzle-orm";
|
|
9
|
+
import { storageConfigCreateSchema, storageConfigUpdateSchema, entitySlugParamSchema, } from "../schemas/index.js";
|
|
10
|
+
import { successResponse, errorResponse, } from "@sudobility/shapeshyft_engine/types";
|
|
11
|
+
export function createStorageRouter(ctx) {
|
|
12
|
+
const { db } = ctx;
|
|
13
|
+
const { entityStorageConfigs } = ctx.tables;
|
|
14
|
+
const { encryptApiKey } = ctx.encryption;
|
|
15
|
+
const { getActor, getEntityWithPermission, getPermissionErrorStatus } = ctx.entityAccess;
|
|
16
|
+
const storageRouter = new Hono();
|
|
17
|
+
/**
|
|
18
|
+
* Convert database storage config to safe response (no credentials)
|
|
19
|
+
*/
|
|
20
|
+
function toSafeConfig(config) {
|
|
21
|
+
return {
|
|
22
|
+
uuid: config.uuid,
|
|
23
|
+
entity_id: config.entity_id,
|
|
24
|
+
provider: config.provider,
|
|
25
|
+
bucket: config.bucket,
|
|
26
|
+
path_prefix: config.path_prefix,
|
|
27
|
+
created_at: config.created_at,
|
|
28
|
+
updated_at: config.updated_at,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// GET storage config for entity
|
|
32
|
+
storageRouter.get("/", zValidator("param", entitySlugParamSchema), async (c) => {
|
|
33
|
+
try {
|
|
34
|
+
const { entitySlug } = c.req.valid("param");
|
|
35
|
+
const result = await getEntityWithPermission(entitySlug, getActor(c));
|
|
36
|
+
if (result.error !== undefined) {
|
|
37
|
+
return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
|
|
38
|
+
}
|
|
39
|
+
const rows = await db
|
|
40
|
+
.select()
|
|
41
|
+
.from(entityStorageConfigs)
|
|
42
|
+
.where(eq(entityStorageConfigs.entity_id, result.entity.id));
|
|
43
|
+
if (rows.length === 0) {
|
|
44
|
+
return c.json(errorResponse("Storage configuration not found"), 404);
|
|
45
|
+
}
|
|
46
|
+
return c.json(successResponse(toSafeConfig(rows[0])));
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error("Error getting storage config:", error);
|
|
50
|
+
return c.json(errorResponse(error.message || "Internal server error"), 500);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
// POST create or update storage config (upsert)
|
|
54
|
+
storageRouter.post("/", zValidator("param", entitySlugParamSchema), zValidator("json", storageConfigCreateSchema), async (c) => {
|
|
55
|
+
try {
|
|
56
|
+
const userId = c.get("userId");
|
|
57
|
+
const { entitySlug } = c.req.valid("param");
|
|
58
|
+
const body = c.req.valid("json");
|
|
59
|
+
const result = await getEntityWithPermission(entitySlug, getActor(c), "canManageApiKeys");
|
|
60
|
+
if (result.error !== undefined) {
|
|
61
|
+
return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
|
|
62
|
+
}
|
|
63
|
+
// Encrypt credentials
|
|
64
|
+
const credentialsJson = JSON.stringify(body.credentials);
|
|
65
|
+
const { encrypted, iv } = encryptApiKey(credentialsJson);
|
|
66
|
+
// Check if config already exists
|
|
67
|
+
const existing = await db
|
|
68
|
+
.select()
|
|
69
|
+
.from(entityStorageConfigs)
|
|
70
|
+
.where(eq(entityStorageConfigs.entity_id, result.entity.id));
|
|
71
|
+
let rows;
|
|
72
|
+
if (existing.length > 0) {
|
|
73
|
+
// Update existing config
|
|
74
|
+
rows = await db
|
|
75
|
+
.update(entityStorageConfigs)
|
|
76
|
+
.set({
|
|
77
|
+
provider: body.provider,
|
|
78
|
+
bucket: body.bucket,
|
|
79
|
+
path_prefix: body.path_prefix ?? null,
|
|
80
|
+
encrypted_credentials: encrypted,
|
|
81
|
+
encryption_iv: iv,
|
|
82
|
+
updated_at: new Date(),
|
|
83
|
+
})
|
|
84
|
+
.where(eq(entityStorageConfigs.entity_id, result.entity.id))
|
|
85
|
+
.returning();
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Create new config
|
|
89
|
+
rows = await db
|
|
90
|
+
.insert(entityStorageConfigs)
|
|
91
|
+
.values({
|
|
92
|
+
entity_id: result.entity.id,
|
|
93
|
+
provider: body.provider,
|
|
94
|
+
bucket: body.bucket,
|
|
95
|
+
path_prefix: body.path_prefix ?? null,
|
|
96
|
+
encrypted_credentials: encrypted,
|
|
97
|
+
encryption_iv: iv,
|
|
98
|
+
created_by: userId,
|
|
99
|
+
})
|
|
100
|
+
.returning();
|
|
101
|
+
}
|
|
102
|
+
return c.json(successResponse(toSafeConfig(rows[0])), existing.length > 0 ? 200 : 201);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error("Error creating/updating storage config:", error);
|
|
106
|
+
return c.json(errorResponse(error.message || "Internal server error"), 500);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
// PUT update storage config (partial update)
|
|
110
|
+
storageRouter.put("/", zValidator("param", entitySlugParamSchema), zValidator("json", storageConfigUpdateSchema), async (c) => {
|
|
111
|
+
try {
|
|
112
|
+
const { entitySlug } = c.req.valid("param");
|
|
113
|
+
const body = c.req.valid("json");
|
|
114
|
+
const result = await getEntityWithPermission(entitySlug, getActor(c), "canManageApiKeys");
|
|
115
|
+
if (result.error !== undefined) {
|
|
116
|
+
return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
|
|
117
|
+
}
|
|
118
|
+
// Check if config exists
|
|
119
|
+
const existing = await db
|
|
120
|
+
.select()
|
|
121
|
+
.from(entityStorageConfigs)
|
|
122
|
+
.where(eq(entityStorageConfigs.entity_id, result.entity.id));
|
|
123
|
+
if (existing.length === 0) {
|
|
124
|
+
return c.json(errorResponse("Storage configuration not found"), 404);
|
|
125
|
+
}
|
|
126
|
+
const current = existing[0];
|
|
127
|
+
// Prepare update values
|
|
128
|
+
let encryptedCredentials = current.encrypted_credentials;
|
|
129
|
+
let encryptionIv = current.encryption_iv;
|
|
130
|
+
if (body.credentials) {
|
|
131
|
+
const credentialsJson = JSON.stringify(body.credentials);
|
|
132
|
+
const { encrypted, iv } = encryptApiKey(credentialsJson);
|
|
133
|
+
encryptedCredentials = encrypted;
|
|
134
|
+
encryptionIv = iv;
|
|
135
|
+
}
|
|
136
|
+
const rows = await db
|
|
137
|
+
.update(entityStorageConfigs)
|
|
138
|
+
.set({
|
|
139
|
+
bucket: body.bucket ?? current.bucket,
|
|
140
|
+
path_prefix: body.path_prefix !== undefined
|
|
141
|
+
? body.path_prefix
|
|
142
|
+
: current.path_prefix,
|
|
143
|
+
encrypted_credentials: encryptedCredentials,
|
|
144
|
+
encryption_iv: encryptionIv,
|
|
145
|
+
updated_at: new Date(),
|
|
146
|
+
})
|
|
147
|
+
.where(eq(entityStorageConfigs.entity_id, result.entity.id))
|
|
148
|
+
.returning();
|
|
149
|
+
return c.json(successResponse(toSafeConfig(rows[0])));
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
console.error("Error updating storage config:", error);
|
|
153
|
+
return c.json(errorResponse(error.message || "Internal server error"), 500);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
// DELETE storage config
|
|
157
|
+
storageRouter.delete("/", zValidator("param", entitySlugParamSchema), async (c) => {
|
|
158
|
+
try {
|
|
159
|
+
const { entitySlug } = c.req.valid("param");
|
|
160
|
+
const result = await getEntityWithPermission(entitySlug, getActor(c), "canManageApiKeys");
|
|
161
|
+
if (result.error !== undefined) {
|
|
162
|
+
return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
|
|
163
|
+
}
|
|
164
|
+
const rows = await db
|
|
165
|
+
.delete(entityStorageConfigs)
|
|
166
|
+
.where(eq(entityStorageConfigs.entity_id, result.entity.id))
|
|
167
|
+
.returning();
|
|
168
|
+
if (rows.length === 0) {
|
|
169
|
+
return c.json(errorResponse("Storage configuration not found"), 404);
|
|
170
|
+
}
|
|
171
|
+
return c.json(successResponse(toSafeConfig(rows[0])));
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error("Error deleting storage config:", error);
|
|
175
|
+
return c.json(errorResponse(error.message || "Internal server error"), 500);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
return storageRouter;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/routes/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Personal API key routes
|
|
3
|
+
* @description CRUD for the personal API keys (`<user prefix>...`) a user can present instead of a
|
|
4
|
+
* Firebase ID token. Keys are scoped to a user (not an entity): a key carries
|
|
5
|
+
* exactly the access its owner has, across every entity they belong to.
|
|
6
|
+
*
|
|
7
|
+
* Two operations hand back a usable secret — create and reveal — and both
|
|
8
|
+
* deliberately require a Firebase ID token. A leaked key can therefore be used
|
|
9
|
+
* to call the API, but not to mint further credentials or read sibling keys.
|
|
10
|
+
*/
|
|
11
|
+
import { Hono } from "hono";
|
|
12
|
+
import type { ServiceContext } from "../context.js";
|
|
13
|
+
export declare function createUserApiKeysRouter(ctx: ServiceContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
14
|
+
//# sourceMappingURL=user-api-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-api-keys.d.ts","sourceRoot":"","sources":["../../src/routes/user-api-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAa5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,cAAc,8EA2U1D"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Personal API key routes
|
|
3
|
+
* @description CRUD for the personal API keys (`<user prefix>...`) a user can present instead of a
|
|
4
|
+
* Firebase ID token. Keys are scoped to a user (not an entity): a key carries
|
|
5
|
+
* exactly the access its owner has, across every entity they belong to.
|
|
6
|
+
*
|
|
7
|
+
* Two operations hand back a usable secret — create and reveal — and both
|
|
8
|
+
* deliberately require a Firebase ID token. A leaked key can therefore be used
|
|
9
|
+
* to call the API, but not to mint further credentials or read sibling keys.
|
|
10
|
+
*/
|
|
11
|
+
import { Hono } from "hono";
|
|
12
|
+
import { zValidator } from "@hono/zod-validator";
|
|
13
|
+
import { eq, and, desc } from "drizzle-orm";
|
|
14
|
+
import { successResponse, errorResponse, } from "@sudobility/shapeshyft_engine/types";
|
|
15
|
+
import { apiKeyIdParamSchema, userApiKeyCreateSchema, userApiKeyUpdateSchema, userIdParamSchema, } from "../schemas/index.js";
|
|
16
|
+
export function createUserApiKeysRouter(ctx) {
|
|
17
|
+
const { db } = ctx;
|
|
18
|
+
const { userApiKeys } = ctx.tables;
|
|
19
|
+
const { generateUserApiKey, hashUserApiKey, encryptUserApiKey, decryptUserApiKey, } = ctx.userApiKeys;
|
|
20
|
+
const { invalidateUserApiKeyCache } = ctx.userApiKeyCache;
|
|
21
|
+
const userApiKeysRouter = new Hono();
|
|
22
|
+
function toSafe(row) {
|
|
23
|
+
return {
|
|
24
|
+
uuid: row.uuid,
|
|
25
|
+
firebase_uid: row.firebase_uid,
|
|
26
|
+
key_name: row.key_name,
|
|
27
|
+
key_prefix: row.key_prefix,
|
|
28
|
+
is_active: row.is_active,
|
|
29
|
+
last_used_at: row.last_used_at?.toISOString() ?? null,
|
|
30
|
+
created_at: row.created_at?.toISOString() ?? null,
|
|
31
|
+
updated_at: row.updated_at?.toISOString() ?? null,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Verify the path userId matches the authenticated user.
|
|
36
|
+
* Returns an error message when it does not.
|
|
37
|
+
*/
|
|
38
|
+
function checkOwnership(c, userId) {
|
|
39
|
+
const authUserId = c.get("userId");
|
|
40
|
+
return authUserId === userId
|
|
41
|
+
? null
|
|
42
|
+
: "You can only manage your own API keys";
|
|
43
|
+
}
|
|
44
|
+
/** Operations that yield a usable secret require a real Firebase token. */
|
|
45
|
+
function requireFirebaseAuth(c) {
|
|
46
|
+
return c.get("authMethod") === "api_key"
|
|
47
|
+
? "This operation requires a Firebase ID token. An API key cannot create or reveal API keys."
|
|
48
|
+
: null;
|
|
49
|
+
}
|
|
50
|
+
// =============================================================================
|
|
51
|
+
// Routes
|
|
52
|
+
// =============================================================================
|
|
53
|
+
/**
|
|
54
|
+
* GET /users/:userId/api-keys
|
|
55
|
+
* List the caller's API keys. Secrets are never included.
|
|
56
|
+
*/
|
|
57
|
+
userApiKeysRouter.get("/", zValidator("param", userIdParamSchema), async (c) => {
|
|
58
|
+
try {
|
|
59
|
+
const { userId } = c.req.valid("param");
|
|
60
|
+
const ownershipError = checkOwnership(c, userId);
|
|
61
|
+
if (ownershipError)
|
|
62
|
+
return c.json(errorResponse(ownershipError), 403);
|
|
63
|
+
const rows = await db
|
|
64
|
+
.select()
|
|
65
|
+
.from(userApiKeys)
|
|
66
|
+
.where(eq(userApiKeys.firebase_uid, userId))
|
|
67
|
+
.orderBy(desc(userApiKeys.created_at));
|
|
68
|
+
return c.json(successResponse(rows.map(toSafe)));
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error("Error listing user API keys:", error);
|
|
72
|
+
const message = error instanceof Error ? error.message : "Internal server error";
|
|
73
|
+
return c.json(errorResponse(message), 500);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* POST /users/:userId/api-keys
|
|
78
|
+
* Create a key. The full value is returned once, here.
|
|
79
|
+
* Requires a Firebase ID token.
|
|
80
|
+
*/
|
|
81
|
+
userApiKeysRouter.post("/", zValidator("param", userIdParamSchema), zValidator("json", userApiKeyCreateSchema), async (c) => {
|
|
82
|
+
try {
|
|
83
|
+
const { userId } = c.req.valid("param");
|
|
84
|
+
const { key_name } = c.req.valid("json");
|
|
85
|
+
const ownershipError = checkOwnership(c, userId);
|
|
86
|
+
if (ownershipError)
|
|
87
|
+
return c.json(errorResponse(ownershipError), 403);
|
|
88
|
+
const authError = requireFirebaseAuth(c);
|
|
89
|
+
if (authError)
|
|
90
|
+
return c.json(errorResponse(authError), 403);
|
|
91
|
+
const { key, prefix } = generateUserApiKey();
|
|
92
|
+
const { encrypted, iv } = encryptUserApiKey(key);
|
|
93
|
+
const rows = await db
|
|
94
|
+
.insert(userApiKeys)
|
|
95
|
+
.values({
|
|
96
|
+
firebase_uid: userId,
|
|
97
|
+
key_name,
|
|
98
|
+
key_hash: hashUserApiKey(key),
|
|
99
|
+
key_prefix: prefix,
|
|
100
|
+
encrypted_key: encrypted,
|
|
101
|
+
encryption_iv: iv,
|
|
102
|
+
})
|
|
103
|
+
.returning();
|
|
104
|
+
const created = {
|
|
105
|
+
...toSafe(rows[0]),
|
|
106
|
+
api_key: key,
|
|
107
|
+
};
|
|
108
|
+
return c.json(successResponse(created), 201);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error("Error creating user API key:", error);
|
|
112
|
+
const message = error instanceof Error ? error.message : "Bad request";
|
|
113
|
+
return c.json(errorResponse(message), 400);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
/**
|
|
117
|
+
* GET /users/:userId/api-keys/:keyId
|
|
118
|
+
* Metadata for one key. The secret is not included.
|
|
119
|
+
*/
|
|
120
|
+
userApiKeysRouter.get("/:keyId", zValidator("param", apiKeyIdParamSchema), async (c) => {
|
|
121
|
+
try {
|
|
122
|
+
const { userId, keyId } = c.req.valid("param");
|
|
123
|
+
const ownershipError = checkOwnership(c, userId);
|
|
124
|
+
if (ownershipError)
|
|
125
|
+
return c.json(errorResponse(ownershipError), 403);
|
|
126
|
+
const rows = await db
|
|
127
|
+
.select()
|
|
128
|
+
.from(userApiKeys)
|
|
129
|
+
.where(and(eq(userApiKeys.firebase_uid, userId), eq(userApiKeys.uuid, keyId)));
|
|
130
|
+
if (rows.length === 0) {
|
|
131
|
+
return c.json(errorResponse("API key not found"), 404);
|
|
132
|
+
}
|
|
133
|
+
return c.json(successResponse(toSafe(rows[0])));
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.error("Error getting user API key:", error);
|
|
137
|
+
const message = error instanceof Error ? error.message : "Internal server error";
|
|
138
|
+
return c.json(errorResponse(message), 500);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
/**
|
|
142
|
+
* GET /users/:userId/api-keys/:keyId/reveal
|
|
143
|
+
* Return the full key so its owner can copy it again.
|
|
144
|
+
* Requires a Firebase ID token.
|
|
145
|
+
*/
|
|
146
|
+
userApiKeysRouter.get("/:keyId/reveal", zValidator("param", apiKeyIdParamSchema), async (c) => {
|
|
147
|
+
try {
|
|
148
|
+
const { userId, keyId } = c.req.valid("param");
|
|
149
|
+
const ownershipError = checkOwnership(c, userId);
|
|
150
|
+
if (ownershipError)
|
|
151
|
+
return c.json(errorResponse(ownershipError), 403);
|
|
152
|
+
const authError = requireFirebaseAuth(c);
|
|
153
|
+
if (authError)
|
|
154
|
+
return c.json(errorResponse(authError), 403);
|
|
155
|
+
const rows = await db
|
|
156
|
+
.select()
|
|
157
|
+
.from(userApiKeys)
|
|
158
|
+
.where(and(eq(userApiKeys.firebase_uid, userId), eq(userApiKeys.uuid, keyId)));
|
|
159
|
+
if (rows.length === 0) {
|
|
160
|
+
return c.json(errorResponse("API key not found"), 404);
|
|
161
|
+
}
|
|
162
|
+
const row = rows[0];
|
|
163
|
+
const apiKey = decryptUserApiKey(row.encrypted_key, row.encryption_iv);
|
|
164
|
+
return c.json(successResponse({ api_key: apiKey }));
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error("Error revealing user API key:", error);
|
|
168
|
+
const message = error instanceof Error ? error.message : "Internal server error";
|
|
169
|
+
return c.json(errorResponse(message), 500);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
/**
|
|
173
|
+
* PUT /users/:userId/api-keys/:keyId
|
|
174
|
+
* Rename a key or toggle it active. Deactivating takes effect immediately.
|
|
175
|
+
*/
|
|
176
|
+
userApiKeysRouter.put("/:keyId", zValidator("param", apiKeyIdParamSchema), zValidator("json", userApiKeyUpdateSchema), async (c) => {
|
|
177
|
+
try {
|
|
178
|
+
const { userId, keyId } = c.req.valid("param");
|
|
179
|
+
const body = c.req.valid("json");
|
|
180
|
+
const ownershipError = checkOwnership(c, userId);
|
|
181
|
+
if (ownershipError)
|
|
182
|
+
return c.json(errorResponse(ownershipError), 403);
|
|
183
|
+
const existing = await db
|
|
184
|
+
.select()
|
|
185
|
+
.from(userApiKeys)
|
|
186
|
+
.where(and(eq(userApiKeys.firebase_uid, userId), eq(userApiKeys.uuid, keyId)));
|
|
187
|
+
if (existing.length === 0) {
|
|
188
|
+
return c.json(errorResponse("API key not found"), 404);
|
|
189
|
+
}
|
|
190
|
+
const rows = await db
|
|
191
|
+
.update(userApiKeys)
|
|
192
|
+
.set({
|
|
193
|
+
key_name: body.key_name ?? existing[0].key_name,
|
|
194
|
+
is_active: body.is_active ?? existing[0].is_active,
|
|
195
|
+
updated_at: new Date(),
|
|
196
|
+
})
|
|
197
|
+
.where(eq(userApiKeys.uuid, keyId))
|
|
198
|
+
.returning();
|
|
199
|
+
// Drop the cached identity so a deactivation is not honored late.
|
|
200
|
+
invalidateUserApiKeyCache(existing[0].key_hash);
|
|
201
|
+
return c.json(successResponse(toSafe(rows[0])));
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
console.error("Error updating user API key:", error);
|
|
205
|
+
const message = error instanceof Error ? error.message : "Bad request";
|
|
206
|
+
return c.json(errorResponse(message), 400);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
/**
|
|
210
|
+
* DELETE /users/:userId/api-keys/:keyId
|
|
211
|
+
* Permanently revoke a key.
|
|
212
|
+
*/
|
|
213
|
+
userApiKeysRouter.delete("/:keyId", zValidator("param", apiKeyIdParamSchema), async (c) => {
|
|
214
|
+
try {
|
|
215
|
+
const { userId, keyId } = c.req.valid("param");
|
|
216
|
+
const ownershipError = checkOwnership(c, userId);
|
|
217
|
+
if (ownershipError)
|
|
218
|
+
return c.json(errorResponse(ownershipError), 403);
|
|
219
|
+
const rows = await db
|
|
220
|
+
.delete(userApiKeys)
|
|
221
|
+
.where(and(eq(userApiKeys.firebase_uid, userId), eq(userApiKeys.uuid, keyId)))
|
|
222
|
+
.returning();
|
|
223
|
+
if (rows.length === 0) {
|
|
224
|
+
return c.json(errorResponse("API key not found"), 404);
|
|
225
|
+
}
|
|
226
|
+
invalidateUserApiKeyCache(rows[0].key_hash);
|
|
227
|
+
return c.json(successResponse(toSafe(rows[0])));
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
console.error("Error deleting user API key:", error);
|
|
231
|
+
const message = error instanceof Error ? error.message : "Bad request";
|
|
232
|
+
return c.json(errorResponse(message), 400);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return userApiKeysRouter;
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=user-api-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-api-keys.js","sourceRoot":"","sources":["../../src/routes/user-api-keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview User routes
|
|
3
|
+
*/
|
|
4
|
+
import { Hono } from "hono";
|
|
5
|
+
import type { ServiceContext } from "../context.js";
|
|
6
|
+
export declare function createUsersRouter(ctx: ServiceContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
7
|
+
//# sourceMappingURL=users.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/routes/users.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAW5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,8EAuHpD"}
|