Various bug fixes (#102)

* feat: set lang in html head

* fix: add # in front of git ref

* fix: remove unused vars from example env

* fix: package name and license field

* fix: enable sourcemap for client and server

* fix: emojis not showing in prod

this is extremely cursed, but it works

* chore: refactor auth manager

* feat: disable invitations if simple auth disabled

* feat: add drop version to footer

* feat: translate auth endpoints

* chore: move oidc module

* feat: add weekly tasks

enabled object cleanup as weekly task

* feat: add timestamp to task log msgs

* feat: add guard to prevent invalid progress %

* fix: add missing global scope to i18n components

* feat: set base url for i18n

* feat: switch task log to json format

* ci: run ci on develop branch only

* fix: UserWidget text not updating #109

* fix: EXTERNAL_URL being computed at build

* feat: add basic language outlines for translation

* feat: add more english dialects
This commit is contained in:
Husky
2025-06-07 23:49:43 -04:00
committed by GitHub
parent 9f5a3b3976
commit 72ae7a2884
43 changed files with 577 additions and 229 deletions

View File

@ -1,9 +1,5 @@
import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
import authManager from "~/server/internal/auth";
export default defineEventHandler(() => {
const authManagers = Object.entries(enabledAuthManagers)
.filter((e) => !!e[1])
.map((e) => e[0]);
return authManagers;
return authManager.getEnabledAuthProviders();
});

View File

@ -2,12 +2,11 @@ import { AuthMec } from "~/prisma/client";
import type { JsonArray } from "@prisma/client/runtime/library";
import { type } from "arktype";
import prisma from "~/server/internal/db/database";
import {
import sessionHandler from "~/server/internal/session";
import authManager, {
checkHashArgon2,
checkHashBcrypt,
} from "~/server/internal/security/simple";
import sessionHandler from "~/server/internal/session";
import { enabledAuthManagers } from "~/server/plugins/04.auth-init";
} from "~/server/internal/auth";
const signinValidator = type({
username: "string",
@ -18,10 +17,12 @@ const signinValidator = type({
export default defineEventHandler<{
body: typeof signinValidator.infer;
}>(async (h3) => {
if (!enabledAuthManagers.Simple)
const t = await useTranslation(h3);
if (!authManager.getAuthProviders().Simple)
throw createError({
statusCode: 403,
statusMessage: "Sign in method not enabled",
statusMessage: t("errors.auth.method.signinDisabled"),
});
const body = signinValidator(await readBody(h3));
@ -55,14 +56,13 @@ export default defineEventHandler<{
if (!authMek)
throw createError({
statusCode: 401,
statusMessage: "Invalid username or password.",
statusMessage: t("errors.auth.invalidUserOrPass"),
});
if (!authMek.user.enabled)
throw createError({
statusCode: 403,
statusMessage:
"Invalid or disabled account. Please contact the server administrator.",
statusMessage: t("errors.auth.disabled"),
});
// LEGACY bcrypt
@ -72,15 +72,14 @@ export default defineEventHandler<{
if (!hash)
throw createError({
statusCode: 403,
statusMessage:
"Invalid password state. Please contact the server administrator.",
statusCode: 500,
statusMessage: t("errors.auth.invalidPassState"),
});
if (!(await checkHashBcrypt(body.password, hash)))
throw createError({
statusCode: 401,
statusMessage: "Invalid username or password.",
statusMessage: t("errors.auth.invalidUserOrPass"),
});
// TODO: send user to forgot password screen or something to force them to change their password to new system
@ -93,14 +92,13 @@ export default defineEventHandler<{
if (!hash || typeof hash !== "string")
throw createError({
statusCode: 500,
statusMessage:
"Invalid password state. Please contact the server administrator.",
statusMessage: t("errors.auth.invalidPassState"),
});
if (!(await checkHashArgon2(body.password, hash)))
throw createError({
statusCode: 401,
statusMessage: "Invalid username or password.",
statusMessage: t("errors.auth.invalidUserOrPass"),
});
await sessionHandler.signin(h3, authMek.userId, body.rememberMe);

View File

@ -1,13 +1,22 @@
import prisma from "~/server/internal/db/database";
import taskHandler from "~/server/internal/tasks";
import authManager from "~/server/internal/auth";
export default defineEventHandler(async (h3) => {
const t = await useTranslation(h3);
if (!authManager.getAuthProviders().Simple)
throw createError({
statusCode: 403,
statusMessage: t("errors.auth.method.signinDisabled"),
});
const query = getQuery(h3);
const id = query.id?.toString();
if (!id)
throw createError({
statusCode: 400,
statusMessage: "id required in fetching invitation",
statusMessage: t("errors.auth.inviteIdRequired"),
});
taskHandler.runTaskGroupByName("cleanup:invitations");
@ -15,7 +24,7 @@ export default defineEventHandler(async (h3) => {
if (!invitation)
throw createError({
statusCode: 404,
statusMessage: "Invalid or expired invitation",
statusMessage: t("errors.auth.invalidInvite"),
});
return invitation;

View File

@ -1,6 +1,6 @@
import { AuthMec } from "~/prisma/client";
import prisma from "~/server/internal/db/database";
import { createHashArgon2 } from "~/server/internal/security/simple";
import authManager, { createHashArgon2 } from "~/server/internal/auth";
import * as jdenticon from "jdenticon";
import objectHandler from "~/server/internal/objects";
import { type } from "arktype";
@ -18,13 +18,21 @@ export const CreateUserValidator = type({
export default defineEventHandler<{
body: typeof CreateUserValidator.infer;
}>(async (h3) => {
const t = await useTranslation(h3);
if (!authManager.getAuthProviders().Simple)
throw createError({
statusCode: 403,
statusMessage: t("errors.auth.method.signinDisabled"),
});
const user = await readValidatedBody(h3, CreateUserValidator);
const invitationId = user.invitation;
if (!invitationId)
throw createError({
statusCode: 401,
statusMessage: "Invalid or expired invitation.",
statusMessage: t("errors.auth.invalidInvite"),
});
const invitation = await prisma.invitation.findUnique({
@ -33,7 +41,7 @@ export default defineEventHandler<{
if (!invitation)
throw createError({
statusCode: 401,
statusMessage: "Invalid or expired invitation.",
statusMessage: t("errors.auth.invalidInvite"),
});
// reuse items from invite
@ -46,7 +54,7 @@ export default defineEventHandler<{
if (existing > 0)
throw createError({
statusCode: 400,
statusMessage: "Username already taken.",
statusMessage: t("errors.auth.usernameTaken"),
});
const userId = randomUUID();