Merge branch 'dev' into main

This commit is contained in:
Lorinc936 authored and GitHub committed 2026-03-24 20:41:22 +01:00
commit d48254fa57
29 files changed
+1252 -1049

No files matched your search

+2 -2
View File
@@ -41,13 +41,13 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@kubernetes/client-node": "^1.4.0",
"@tanstack/react-query": "^5.90.21",
"@tanstack/react-query": "^5.91.2",
"@trpc/client": "^11.13.4",
"@trpc/react-query": "^11.13.4",
"@trpc/server": "^11.13.4",
"@trpc/tanstack-react-query": "^11.13.4",
"lodash.clonedeep": "^4.5.0",
"next": "16.1.7",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"superjson": "2.2.6",
+51 -4
View File
@@ -1,11 +1,13 @@
import { TRPCError } from "@trpc/server";
import type { MySqlRawQueryResult } from "drizzle-orm/mysql2";
import type { QueryResult } from "pg";
import { z } from "zod/v4";
import { createSaltAsync, hashPasswordAsync } from "@homarr/auth";
import { createId } from "@homarr/common";
import { createLogger } from "@homarr/core/infrastructure/logs";
import type { Database } from "@homarr/db";
import { and, eq, like } from "@homarr/db";
import { and, eq, handleTransactionsAsync, like } from "@homarr/db";
import { getMaxGroupPositionAsync } from "@homarr/db/queries";
import { boards, groupMembers, groupPermissions, groups, invites, users } from "@homarr/db/schema";
import { selectUserSchema } from "@homarr/db/validationSchemas";
@@ -90,10 +92,55 @@ export const userRouter = createTRPCRouter({
await checkUsernameAlreadyTakenAndThrowAsync(ctx.db, "credentials", input.username);
await createUserAsync(ctx.db, input);
const salt = await createSaltAsync();
const hashedPassword = await hashPasswordAsync(input.password, salt);
// Delete invite as it's used
await ctx.db.delete(invites).where(inviteWhere);
const userId = createId();
const user = {
id: userId,
name: input.username,
password: hashedPassword,
salt,
};
await handleTransactionsAsync(ctx.db, {
async handleAsync(db, schema) {
await db.transaction(async (trx) => {
await trx.insert(schema.users).values(user);
// Delete invite as it's used
const queryResult = (await trx.delete(schema.invites).where(inviteWhere)) as
| QueryResult
| MySqlRawQueryResult;
let count = 0;
if (Array.isArray(queryResult)) {
count = queryResult[0].affectedRows;
} else {
count = queryResult.rowCount ?? 0;
}
if (count === 0) {
throw new TRPCError({
code: "FORBIDDEN",
message: "Invalid invite",
});
}
});
},
handleSync(db) {
db.transaction((trx) => {
trx.insert(users).values(user).run();
// Delete invite as it's used
const result = trx.delete(invites).where(inviteWhere).run();
if (result.changes === 0) {
throw new TRPCError({
code: "FORBIDDEN",
message: "Invalid invite",
});
}
});
},
});
}),
create: permissionRequiredProcedure
.requiresPermission("admin")
+1 -1
View File
@@ -34,7 +34,7 @@
"bcrypt": "^6.0.0",
"cookies": "^0.9.1",
"ldapts": "8.1.7",
"next": "16.1.7",
"next": "16.2.0",
"next-auth": "5.0.0-beta.30",
"react": "19.2.4",
"react-dom": "19.2.4",
+1 -1
View File
@@ -30,7 +30,7 @@
"@paralleldrive/cuid2": "^3.3.0",
"cookie": "1.1.1",
"dayjs": "^1.11.20",
"next": "16.1.7",
"next": "16.2.0",
"octokit": "^5.0.5",
"react": "19.2.4",
"react-dom": "19.2.4",
+2 -2
View File
@@ -41,8 +41,8 @@
"better-sqlite3": "^12.6.2",
"dns-caching": "^0.2.9",
"drizzle-orm": "^0.45.1",
"ioredis": "5.10.0",
"mysql2": "3.19.1",
"ioredis": "5.10.1",
"mysql2": "3.20.0",
"pg": "^8.20.0",
"superjson": "2.2.6",
"winston": "3.19.0",
+1 -1
View File
@@ -28,7 +28,7 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/core": "workspace:^0.1.0",
"@homarr/cron-jobs": "workspace:^0.1.0",
"@tanstack/react-query": "^5.90.21",
"@tanstack/react-query": "^5.91.2",
"@trpc/client": "^11.13.4",
"@trpc/server": "^11.13.4",
"@trpc/tanstack-react-query": "^11.13.4",
+5 -5
View File
@@ -47,16 +47,16 @@
"@homarr/core": "workspace:^0.1.0",
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/core": "^8.3.17",
"@mantine/core": "^8.3.18",
"@paralleldrive/cuid2": "^3.3.0",
"@testcontainers/mysql": "^11.12.0",
"@testcontainers/postgresql": "^11.12.0",
"@testcontainers/mysql": "^11.13.0",
"@testcontainers/postgresql": "^11.13.0",
"better-sqlite3": "^12.6.2",
"dotenv": "^17.3.1",
"drizzle-kit": "^0.31.9",
"drizzle-kit": "^0.31.10",
"drizzle-orm": "^0.45.1",
"drizzle-zod": "^0.8.3",
"mysql2": "3.19.1",
"mysql2": "3.20.0",
"pg": "^8.20.0",
"superjson": "2.2.6"
},
+1 -1
View File
@@ -24,7 +24,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0",
"fast-xml-parser": "^5.5.5",
"fast-xml-parser": "^5.5.7",
"zod": "^4.2.1"
},
"devDependencies": {
+1 -1
View File
@@ -26,7 +26,7 @@
"@homarr/common": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/form": "^8.3.17",
"@mantine/form": "^8.3.18",
"mantine-form-zod-resolver": "^1.3.0",
"zod": "^4.2.1"
},
+1 -1
View File
@@ -30,7 +30,7 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.17",
"@mantine/core": "^8.3.18",
"react": "19.2.4",
"zod": "^4.2.1"
},
+1 -1
View File
@@ -38,7 +38,7 @@
"@homarr/redis": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@immich/sdk": "^2.5.6",
"@immich/sdk": "^2.6.0",
"@jellyfin/sdk": "^0.13.0",
"@octokit/auth-app": "^8.2.0",
"ical.js": "^2.2.1",
+2 -2
View File
@@ -33,10 +33,10 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.17",
"@mantine/core": "^8.3.18",
"@tabler/icons-react": "^3.40.0",
"dayjs": "^1.11.20",
"next": "16.1.7",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"zod": "^4.2.1"
+2 -2
View File
@@ -24,8 +24,8 @@
"dependencies": {
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.17",
"@mantine/hooks": "^8.3.17",
"@mantine/core": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"react": "19.2.4"
},
"devDependencies": {
+1 -1
View File
@@ -24,7 +24,7 @@
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/ui": "workspace:^0.1.0",
"@mantine/notifications": "^8.3.17",
"@mantine/notifications": "^8.3.18",
"@tabler/icons-react": "^3.40.0"
},
"devDependencies": {
+4 -4
View File
@@ -37,10 +37,10 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.17",
"@mantine/hooks": "^8.3.17",
"@mantine/core": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"adm-zip": "0.5.16",
"next": "16.1.7",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"superjson": "2.2.6",
@@ -51,7 +51,7 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/adm-zip": "0.5.7",
"@types/adm-zip": "0.5.8",
"eslint": "^9.39.4",
"typescript": "^5.9.3"
}
+1 -1
View File
@@ -26,7 +26,7 @@
"@homarr/core": "workspace:^",
"@homarr/db": "workspace:^",
"@homarr/definitions": "workspace:^",
"ioredis": "5.10.0",
"ioredis": "5.10.1",
"superjson": "2.2.6"
},
"devDependencies": {
+2 -2
View File
@@ -25,8 +25,8 @@
"dependencies": {
"@homarr/db": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@mantine/dates": "^8.3.17",
"next": "16.1.7",
"@mantine/dates": "^8.3.18",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4"
},
+4 -4
View File
@@ -33,12 +33,12 @@
"@homarr/settings": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@mantine/core": "^8.3.17",
"@mantine/hooks": "^8.3.17",
"@mantine/spotlight": "^8.3.17",
"@mantine/core": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"@mantine/spotlight": "^8.3.18",
"@tabler/icons-react": "^3.40.0",
"jotai": "^2.18.1",
"next": "16.1.7",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"use-deep-compare-effect": "^1.8.1"
+1 -1
View File
@@ -32,7 +32,7 @@
"dayjs": "^1.11.20",
"deepmerge": "4.3.1",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.1.7",
"next": "16.2.0",
"next-intl": "4.8.3",
"react": "19.2.4",
"react-dom": "19.2.4"
+35 -35
View File
@@ -2007,7 +2007,7 @@
"label": ""
},
"showRecentActivity": {
"label": ""
"label": "Afficher l'activité récente"
},
"showViolations": {
"label": ""
@@ -2015,18 +2015,18 @@
},
"stats": {
"activeStreams": "",
"totalUsers": "",
"totalUsers": "Utilisateurs totaux",
"transcodes": "",
"bandwidth": ""
"bandwidth": "Bande passante"
},
"streams": {
"empty": "",
"user": "",
"user": "Utilisateur",
"media": "",
"state": "",
"quality": "",
"device": "",
"progress": "",
"quality": "Qualité",
"device": "Appareil",
"progress": "Progression",
"videoDecision": {
"directPlay": "",
"transcode": "",
@@ -2034,16 +2034,16 @@
}
},
"recentActivity": {
"title": "",
"empty": "",
"title": "Activité récente",
"empty": "Aucune activité récente",
"watched": "",
"partial": ""
},
"violations": {
"title": "",
"empty": "",
"rule": "",
"user": ""
"rule": "Règle",
"user": "Utilisateur"
},
"noSectionsEnabled": "",
"error": {
@@ -2147,50 +2147,50 @@
}
},
"immich-serverStats": {
"name": "",
"description": "",
"name": "Statistiques du serveur Immich",
"description": "Informations sur votre instance Immich",
"option": {
"showUsers": {
"label": "",
"description": ""
"label": "Afficher les utilisateurs",
"description": "Afficher le nombre d'utilisateurs de l'instance"
},
"showPhotos": {
"label": "",
"description": ""
"label": "Afficher les photos",
"description": "Afficher le nombre de photos de l'instance"
},
"showVideos": {
"label": "",
"description": ""
"label": "Afficher les vidéos",
"description": "Afficher le nombre de vidéos de l'instance"
},
"showStorage": {
"label": "",
"description": ""
"label": "Affiche le stockage",
"description": "Afficher le stockage total utilisé"
}
},
"users": "",
"photos": "",
"videos": "",
"storage": ""
"users": "Utilisateurs",
"photos": "Photos",
"videos": "Vidéos",
"storage": "Stockage utilisé"
},
"immich-albumCarousel": {
"name": "",
"name": "Album Immich",
"option": {
"albumId": {
"label": "",
"description": ""
"label": "Identifiant de l'album",
"description": "C'est l'identifiant unique qui correspond à l'album Immich. Vous pouvez le trouver en ouvrant un album et copiant l'identifiant unique depuis l'URL, par exemple 'a21aca09-9f05-47dc-b1a1-7b53c547226e'"
},
"rotationIntervalSeconds": {
"label": "",
"description": ""
"label": "Intervalle en secondes",
"description": "Rotation entre les images de l'album chaque X secondes. Doit être entre 1 et 3600."
},
"showPhotoInfo": {
"label": "",
"description": ""
"label": "Afficher les informations de la photo",
"description": "Afficher la date et l'index de la photo en bas du diaporama"
}
},
"description": "",
"noAlbumSelected": "",
"noPhotos": ""
"description": "Diaporama de photos dans votre album Immich",
"noAlbumSelected": "Aucun album sélectionné, modifier le widget et choisissez un album",
"noPhotos": "Aucune photo dans cet album"
},
"downloads": {
"name": "Client de téléchargement",
+4 -4
View File
@@ -30,13 +30,13 @@
"@homarr/settings": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/core": "^8.3.17",
"@mantine/dates": "^8.3.17",
"@mantine/hooks": "^8.3.17",
"@mantine/core": "^8.3.18",
"@mantine/dates": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"@tabler/icons-react": "^3.40.0",
"crypto-js": "^4.2.0",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.1.7",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"svgson": "^5.3.1"
+20 -20
View File
@@ -48,31 +48,31 @@
"@homarr/translation": "workspace:^0.1.0",
"@homarr/ui": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0",
"@mantine/charts": "^8.3.17",
"@mantine/core": "^8.3.17",
"@mantine/hooks": "^8.3.17",
"@mantine/charts": "^8.3.18",
"@mantine/core": "^8.3.18",
"@mantine/hooks": "^8.3.18",
"@tabler/icons-react": "^3.40.0",
"@tiptap/extension-color": "3.20.2",
"@tiptap/extension-highlight": "3.20.2",
"@tiptap/extension-image": "3.20.2",
"@tiptap/extension-link": "^3.20.2",
"@tiptap/extension-placeholder": "^3.20.2",
"@tiptap/extension-table": "3.20.2",
"@tiptap/extension-table-cell": "3.20.2",
"@tiptap/extension-table-header": "3.20.2",
"@tiptap/extension-table-row": "3.20.2",
"@tiptap/extension-task-item": "3.20.2",
"@tiptap/extension-task-list": "3.20.2",
"@tiptap/extension-text-align": "3.20.2",
"@tiptap/extension-text-style": "3.20.2",
"@tiptap/extension-underline": "3.20.2",
"@tiptap/react": "^3.20.2",
"@tiptap/starter-kit": "^3.20.2",
"@tiptap/extension-color": "3.20.4",
"@tiptap/extension-highlight": "3.20.4",
"@tiptap/extension-image": "3.20.4",
"@tiptap/extension-link": "^3.20.4",
"@tiptap/extension-placeholder": "^3.20.4",
"@tiptap/extension-table": "3.20.4",
"@tiptap/extension-table-cell": "3.20.4",
"@tiptap/extension-table-header": "3.20.4",
"@tiptap/extension-table-row": "3.20.4",
"@tiptap/extension-task-item": "3.20.4",
"@tiptap/extension-task-list": "3.20.4",
"@tiptap/extension-text-align": "3.20.4",
"@tiptap/extension-text-style": "3.20.4",
"@tiptap/extension-underline": "3.20.4",
"@tiptap/react": "^3.20.4",
"@tiptap/starter-kit": "^3.20.4",
"clsx": "^2.1.1",
"dayjs": "^1.11.20",
"mantine-form-zod-resolver": "^1.3.0",
"mantine-react-table": "2.0.0-beta.9",
"next": "16.1.7",
"next": "16.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-markdown": "^10.1.0",