feat(integrations): add app linking (#4338)
This commit is contained in:
@@ -6,6 +6,7 @@ import { decryptSecret, encryptSecret } from "@homarr/common/server";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, asc, eq, handleTransactionsAsync, inArray, like, or } from "@homarr/db";
|
||||
import {
|
||||
apps,
|
||||
groupMembers,
|
||||
groupPermissions,
|
||||
integrationGroupPermissions,
|
||||
@@ -212,6 +213,14 @@ export const integrationRouter = createTRPCRouter({
|
||||
updatedAt: true,
|
||||
},
|
||||
},
|
||||
app: {
|
||||
columns: {
|
||||
id: true,
|
||||
name: true,
|
||||
iconUrl: true,
|
||||
href: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -233,6 +242,7 @@ export const integrationRouter = createTRPCRouter({
|
||||
value: integrationSecretKindObject[secret.kind].isPublic ? decryptSecret(secret.value) : null,
|
||||
updatedAt: secret.updatedAt,
|
||||
})),
|
||||
app: integration.app,
|
||||
};
|
||||
}),
|
||||
create: permissionRequiredProcedure
|
||||
@@ -245,6 +255,13 @@ export const integrationRouter = createTRPCRouter({
|
||||
url: input.url,
|
||||
});
|
||||
|
||||
if (input.app && "name" in input.app && !ctx.session.user.permissions.includes("app-create")) {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
message: "Permission denied",
|
||||
});
|
||||
}
|
||||
|
||||
const result = await testConnectionAsync({
|
||||
id: "new",
|
||||
name: input.name,
|
||||
@@ -267,12 +284,15 @@ export const integrationRouter = createTRPCRouter({
|
||||
};
|
||||
}
|
||||
|
||||
const appId = await createAppIfNecessaryAsync(ctx.db, input.app);
|
||||
|
||||
const integrationId = createId();
|
||||
await ctx.db.insert(integrations).values({
|
||||
id: integrationId,
|
||||
name: input.name,
|
||||
url: input.url,
|
||||
kind: input.kind,
|
||||
appId,
|
||||
});
|
||||
|
||||
if (input.secrets.length >= 1) {
|
||||
@@ -358,6 +378,7 @@ export const integrationRouter = createTRPCRouter({
|
||||
.set({
|
||||
name: input.name,
|
||||
url: input.url,
|
||||
appId: input.appId,
|
||||
})
|
||||
.where(eq(integrations.id, input.id));
|
||||
|
||||
@@ -652,3 +673,30 @@ const addSecretAsync = async (db: Database, input: AddSecretInput) => {
|
||||
integrationId: input.integrationId,
|
||||
});
|
||||
};
|
||||
|
||||
const createAppIfNecessaryAsync = async (db: Database, app: z.infer<typeof integrationCreateSchema>["app"]) => {
|
||||
if (!app) return null;
|
||||
if ("id" in app) return app.id;
|
||||
|
||||
logger.info("Creating app", {
|
||||
name: app.name,
|
||||
url: app.href,
|
||||
});
|
||||
const appId = createId();
|
||||
await db.insert(apps).values({
|
||||
id: appId,
|
||||
name: app.name,
|
||||
description: app.description,
|
||||
iconUrl: app.iconUrl,
|
||||
href: app.href,
|
||||
pingUrl: app.pingUrl,
|
||||
});
|
||||
|
||||
logger.info("Created app", {
|
||||
id: appId,
|
||||
name: app.name,
|
||||
url: app.href,
|
||||
});
|
||||
|
||||
return appId;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user