mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-27 08:50:56 +01:00
feat(spotlight): add default search engine (#1807)
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { createId, eq, like, sql } from "@homarr/db";
|
||||
import { searchEngines } from "@homarr/db/schema";
|
||||
import { asc, createId, eq, like, sql } from "@homarr/db";
|
||||
import { getServerSettingByKeyAsync } from "@homarr/db/queries";
|
||||
import { searchEngines, users } from "@homarr/db/schema";
|
||||
import { integrationCreator } from "@homarr/integrations";
|
||||
import { validation } from "@homarr/validation";
|
||||
import { validation, z } from "@homarr/validation";
|
||||
|
||||
import { createOneIntegrationMiddleware } from "../../middlewares/integration";
|
||||
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
|
||||
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure, publicProcedure } from "../../trpc";
|
||||
|
||||
export const searchEngineRouter = createTRPCRouter({
|
||||
getPaginated: protectedProcedure.input(validation.common.paginated).query(async ({ input, ctx }) => {
|
||||
@@ -29,6 +30,21 @@ export const searchEngineRouter = createTRPCRouter({
|
||||
totalCount: searchEngineCount[0]?.count ?? 0,
|
||||
};
|
||||
}),
|
||||
getSelectable: protectedProcedure
|
||||
.input(z.object({ withIntegrations: z.boolean() }).default({ withIntegrations: true }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
return await ctx.db.query.searchEngines
|
||||
.findMany({
|
||||
orderBy: asc(searchEngines.name),
|
||||
where: input.withIntegrations ? undefined : eq(searchEngines.type, "generic"),
|
||||
columns: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
})
|
||||
.then((engines) => engines.map((engine) => ({ value: engine.id, label: engine.name })));
|
||||
}),
|
||||
|
||||
byId: protectedProcedure.input(validation.common.byId).query(async ({ ctx, input }) => {
|
||||
const searchEngine = await ctx.db.query.searchEngines.findFirst({
|
||||
where: eq(searchEngines.id, input.id),
|
||||
@@ -55,6 +71,54 @@ export const searchEngineRouter = createTRPCRouter({
|
||||
urlTemplate: searchEngine.urlTemplate!,
|
||||
};
|
||||
}),
|
||||
getDefaultSearchEngine: publicProcedure.query(async ({ ctx }) => {
|
||||
const userDefaultId = ctx.session?.user.id
|
||||
? ((await ctx.db.query.users
|
||||
.findFirst({
|
||||
where: eq(users.id, ctx.session.user.id),
|
||||
columns: {
|
||||
defaultSearchEngineId: true,
|
||||
},
|
||||
})
|
||||
.then((user) => user?.defaultSearchEngineId)) ?? null)
|
||||
: null;
|
||||
|
||||
if (userDefaultId) {
|
||||
return await ctx.db.query.searchEngines.findFirst({
|
||||
where: eq(searchEngines.id, userDefaultId),
|
||||
with: {
|
||||
integration: {
|
||||
columns: {
|
||||
kind: true,
|
||||
url: true,
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const serverDefaultId = await getServerSettingByKeyAsync(ctx.db, "search").then(
|
||||
(setting) => setting.defaultSearchEngineId,
|
||||
);
|
||||
|
||||
if (serverDefaultId) {
|
||||
return await ctx.db.query.searchEngines.findFirst({
|
||||
where: eq(searchEngines.id, serverDefaultId),
|
||||
with: {
|
||||
integration: {
|
||||
columns: {
|
||||
kind: true,
|
||||
url: true,
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}),
|
||||
search: protectedProcedure.input(validation.common.search).query(async ({ ctx, input }) => {
|
||||
return await ctx.db.query.searchEngines.findMany({
|
||||
where: like(searchEngines.short, `${input.query.toLowerCase().trim()}%`),
|
||||
|
||||
@@ -211,6 +211,7 @@ export const userRouter = createTRPCRouter({
|
||||
homeBoardId: true,
|
||||
firstDayOfWeek: true,
|
||||
pingIconsEnabled: true,
|
||||
defaultSearchEngineId: true,
|
||||
}),
|
||||
)
|
||||
.meta({ openapi: { method: "GET", path: "/api/users/{userId}", tags: ["users"], protect: true } })
|
||||
@@ -233,6 +234,7 @@ export const userRouter = createTRPCRouter({
|
||||
homeBoardId: true,
|
||||
firstDayOfWeek: true,
|
||||
pingIconsEnabled: true,
|
||||
defaultSearchEngineId: true,
|
||||
},
|
||||
where: eq(users.id, input.userId),
|
||||
});
|
||||
@@ -406,6 +408,43 @@ export const userRouter = createTRPCRouter({
|
||||
})
|
||||
.where(eq(users.id, input.userId));
|
||||
}),
|
||||
changeDefaultSearchEngine: protectedProcedure
|
||||
.input(
|
||||
convertIntersectionToZodObject(validation.user.changeDefaultSearchEngine.and(z.object({ userId: z.string() }))),
|
||||
)
|
||||
.output(z.void())
|
||||
.meta({ openapi: { method: "PATCH", path: "/api/users/changeSearchEngine", tags: ["users"], protect: true } })
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const user = ctx.session.user;
|
||||
// Only admins can change other users passwords
|
||||
if (!user.permissions.includes("admin") && user.id !== input.userId) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "User not found",
|
||||
});
|
||||
}
|
||||
|
||||
const dbUser = await ctx.db.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
},
|
||||
where: eq(users.id, input.userId),
|
||||
});
|
||||
|
||||
if (!dbUser) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "User not found",
|
||||
});
|
||||
}
|
||||
|
||||
await ctx.db
|
||||
.update(users)
|
||||
.set({
|
||||
defaultSearchEngineId: input.defaultSearchEngineId,
|
||||
})
|
||||
.where(eq(users.id, input.userId));
|
||||
}),
|
||||
changeColorScheme: protectedProcedure
|
||||
.input(validation.user.changeColorScheme)
|
||||
.output(z.void())
|
||||
|
||||
Reference in New Issue
Block a user