More fixes and linting
This commit is contained in:
parent
b120071762
commit
ff48b7c464
6 changed files with 1071 additions and 1101 deletions
|
|
@ -116,10 +116,7 @@ export default function LoginPage() {
|
||||||
// Show 2FA verification form
|
// Show 2FA verification form
|
||||||
if (pendingSessionId) {
|
if (pendingSessionId) {
|
||||||
return (
|
return (
|
||||||
<AuthLayout
|
<AuthLayout title="Two-Factor Authentication" description="Enter the 6-digit code from your authenticator app">
|
||||||
title="Two-Factor Authentication"
|
|
||||||
description="Enter the 6-digit code from your authenticator app"
|
|
||||||
>
|
|
||||||
<form onSubmit={handleTwoFactorSubmit} className="space-y-4">
|
<form onSubmit={handleTwoFactorSubmit} className="space-y-4">
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<Label htmlFor="2fa-code">Authentication Code</Label>
|
<Label htmlFor="2fa-code">Authentication Code</Label>
|
||||||
|
|
|
||||||
|
|
@ -150,10 +150,14 @@ export default function Settings({ loaderData }: Route.ComponentProps) {
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} else {
|
} else {
|
||||||
toast.error("Failed to enable 2FA", { description: data.message });
|
toast.error("Failed to enable 2FA", { description: data.message });
|
||||||
|
setEnable2faDialogOpen(false);
|
||||||
|
resetEnable2faDialog();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast.error("Failed to enable 2FA", { description: error.message });
|
toast.error("Failed to enable 2FA", { description: error.message });
|
||||||
|
setEnable2faDialogOpen(false);
|
||||||
|
resetEnable2faDialog();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -169,10 +173,14 @@ export default function Settings({ loaderData }: Route.ComponentProps) {
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} else {
|
} else {
|
||||||
toast.error("Failed to disable 2FA", { description: data.message });
|
toast.error("Failed to disable 2FA", { description: data.message });
|
||||||
|
setDisable2faDialogOpen(false);
|
||||||
|
resetDisable2faDialog();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast.error("Failed to disable 2FA", { description: error.message });
|
toast.error("Failed to disable 2FA", { description: error.message });
|
||||||
|
setDisable2faDialogOpen(false);
|
||||||
|
resetDisable2faDialog();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -350,10 +358,20 @@ export default function Settings({ loaderData }: Route.ComponentProps) {
|
||||||
<CardTitle className="flex items-center gap-2">
|
<CardTitle className="flex items-center gap-2">
|
||||||
<Shield className="size-5" />
|
<Shield className="size-5" />
|
||||||
Two-Factor Authentication
|
Two-Factor Authentication
|
||||||
{twoFactorStatus.data && (
|
{twoFactorStatus.isLoading ? (
|
||||||
|
<Badge variant="secondary" className="ml-2">
|
||||||
|
Loading...
|
||||||
|
</Badge>
|
||||||
|
) : twoFactorStatus.isError ? (
|
||||||
|
<Badge variant="secondary" className="ml-2">
|
||||||
|
Status unavailable
|
||||||
|
</Badge>
|
||||||
|
) : (
|
||||||
|
twoFactorStatus.data && (
|
||||||
<Badge variant={twoFactorStatus.data.enabled ? "success" : "secondary"} className="ml-2">
|
<Badge variant={twoFactorStatus.data.enabled ? "success" : "secondary"} className="ml-2">
|
||||||
{twoFactorStatus.data.enabled ? "Enabled" : "Disabled"}
|
{twoFactorStatus.data.enabled ? "Enabled" : "Disabled"}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="mt-1.5">Add an extra layer of security to your account</CardDescription>
|
<CardDescription className="mt-1.5">Add an extra layer of security to your account</CardDescription>
|
||||||
|
|
@ -364,7 +382,12 @@ export default function Settings({ loaderData }: Route.ComponentProps) {
|
||||||
authenticator app when logging in.
|
authenticator app when logging in.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{twoFactorStatus.data?.enabled ? (
|
{twoFactorStatus.isLoading || twoFactorStatus.isError ? (
|
||||||
|
<Button variant="outline" disabled>
|
||||||
|
<Shield size={16} className="mr-2" />
|
||||||
|
{twoFactorStatus.isLoading ? "Loading..." : "Status unavailable"}
|
||||||
|
</Button>
|
||||||
|
) : twoFactorStatus.data?.enabled ? (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={disable2faDialogOpen}
|
open={disable2faDialogOpen}
|
||||||
onOpenChange={(open) => {
|
onOpenChange={(open) => {
|
||||||
|
|
|
||||||
|
|
@ -109,10 +109,7 @@
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"backup_schedule_mirrors_table_schedule_id_repository_id_unique": {
|
"backup_schedule_mirrors_table_schedule_id_repository_id_unique": {
|
||||||
"name": "backup_schedule_mirrors_table_schedule_id_repository_id_unique",
|
"name": "backup_schedule_mirrors_table_schedule_id_repository_id_unique",
|
||||||
"columns": [
|
"columns": ["schedule_id", "repository_id"],
|
||||||
"schedule_id",
|
|
||||||
"repository_id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -121,12 +118,8 @@
|
||||||
"name": "backup_schedule_mirrors_table_schedule_id_backup_schedules_table_id_fk",
|
"name": "backup_schedule_mirrors_table_schedule_id_backup_schedules_table_id_fk",
|
||||||
"tableFrom": "backup_schedule_mirrors_table",
|
"tableFrom": "backup_schedule_mirrors_table",
|
||||||
"tableTo": "backup_schedules_table",
|
"tableTo": "backup_schedules_table",
|
||||||
"columnsFrom": [
|
"columnsFrom": ["schedule_id"],
|
||||||
"schedule_id"
|
"columnsTo": ["id"],
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
|
|
@ -134,12 +127,8 @@
|
||||||
"name": "backup_schedule_mirrors_table_repository_id_repositories_table_id_fk",
|
"name": "backup_schedule_mirrors_table_repository_id_repositories_table_id_fk",
|
||||||
"tableFrom": "backup_schedule_mirrors_table",
|
"tableFrom": "backup_schedule_mirrors_table",
|
||||||
"tableTo": "repositories_table",
|
"tableTo": "repositories_table",
|
||||||
"columnsFrom": [
|
"columnsFrom": ["repository_id"],
|
||||||
"repository_id"
|
"columnsTo": ["id"],
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
}
|
}
|
||||||
|
|
@ -212,12 +201,8 @@
|
||||||
"name": "backup_schedule_notifications_table_schedule_id_backup_schedules_table_id_fk",
|
"name": "backup_schedule_notifications_table_schedule_id_backup_schedules_table_id_fk",
|
||||||
"tableFrom": "backup_schedule_notifications_table",
|
"tableFrom": "backup_schedule_notifications_table",
|
||||||
"tableTo": "backup_schedules_table",
|
"tableTo": "backup_schedules_table",
|
||||||
"columnsFrom": [
|
"columnsFrom": ["schedule_id"],
|
||||||
"schedule_id"
|
"columnsTo": ["id"],
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
|
|
@ -225,22 +210,15 @@
|
||||||
"name": "backup_schedule_notifications_table_destination_id_notification_destinations_table_id_fk",
|
"name": "backup_schedule_notifications_table_destination_id_notification_destinations_table_id_fk",
|
||||||
"tableFrom": "backup_schedule_notifications_table",
|
"tableFrom": "backup_schedule_notifications_table",
|
||||||
"tableTo": "notification_destinations_table",
|
"tableTo": "notification_destinations_table",
|
||||||
"columnsFrom": [
|
"columnsFrom": ["destination_id"],
|
||||||
"destination_id"
|
"columnsTo": ["id"],
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"compositePrimaryKeys": {
|
"compositePrimaryKeys": {
|
||||||
"backup_schedule_notifications_table_schedule_id_destination_id_pk": {
|
"backup_schedule_notifications_table_schedule_id_destination_id_pk": {
|
||||||
"columns": [
|
"columns": ["schedule_id", "destination_id"],
|
||||||
"schedule_id",
|
|
||||||
"destination_id"
|
|
||||||
],
|
|
||||||
"name": "backup_schedule_notifications_table_schedule_id_destination_id_pk"
|
"name": "backup_schedule_notifications_table_schedule_id_destination_id_pk"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -395,16 +373,12 @@
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"backup_schedules_table_short_id_unique": {
|
"backup_schedules_table_short_id_unique": {
|
||||||
"name": "backup_schedules_table_short_id_unique",
|
"name": "backup_schedules_table_short_id_unique",
|
||||||
"columns": [
|
"columns": ["short_id"],
|
||||||
"short_id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
},
|
},
|
||||||
"backup_schedules_table_name_unique": {
|
"backup_schedules_table_name_unique": {
|
||||||
"name": "backup_schedules_table_name_unique",
|
"name": "backup_schedules_table_name_unique",
|
||||||
"columns": [
|
"columns": ["name"],
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -413,12 +387,8 @@
|
||||||
"name": "backup_schedules_table_volume_id_volumes_table_id_fk",
|
"name": "backup_schedules_table_volume_id_volumes_table_id_fk",
|
||||||
"tableFrom": "backup_schedules_table",
|
"tableFrom": "backup_schedules_table",
|
||||||
"tableTo": "volumes_table",
|
"tableTo": "volumes_table",
|
||||||
"columnsFrom": [
|
"columnsFrom": ["volume_id"],
|
||||||
"volume_id"
|
"columnsTo": ["id"],
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
},
|
},
|
||||||
|
|
@ -426,12 +396,8 @@
|
||||||
"name": "backup_schedules_table_repository_id_repositories_table_id_fk",
|
"name": "backup_schedules_table_repository_id_repositories_table_id_fk",
|
||||||
"tableFrom": "backup_schedules_table",
|
"tableFrom": "backup_schedules_table",
|
||||||
"tableTo": "repositories_table",
|
"tableTo": "repositories_table",
|
||||||
"columnsFrom": [
|
"columnsFrom": ["repository_id"],
|
||||||
"repository_id"
|
"columnsTo": ["id"],
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
}
|
}
|
||||||
|
|
@ -499,9 +465,7 @@
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"notification_destinations_table_name_unique": {
|
"notification_destinations_table_name_unique": {
|
||||||
"name": "notification_destinations_table_name_unique",
|
"name": "notification_destinations_table_name_unique",
|
||||||
"columns": [
|
"columns": ["name"],
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -598,9 +562,7 @@
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"repositories_table_short_id_unique": {
|
"repositories_table_short_id_unique": {
|
||||||
"name": "repositories_table_short_id_unique",
|
"name": "repositories_table_short_id_unique",
|
||||||
"columns": [
|
"columns": ["short_id"],
|
||||||
"short_id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -648,12 +610,8 @@
|
||||||
"name": "sessions_table_user_id_users_table_id_fk",
|
"name": "sessions_table_user_id_users_table_id_fk",
|
||||||
"tableFrom": "sessions_table",
|
"tableFrom": "sessions_table",
|
||||||
"tableTo": "users_table",
|
"tableTo": "users_table",
|
||||||
"columnsFrom": [
|
"columnsFrom": ["user_id"],
|
||||||
"user_id"
|
"columnsTo": ["id"],
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
"onDelete": "cascade",
|
||||||
"onUpdate": "no action"
|
"onUpdate": "no action"
|
||||||
}
|
}
|
||||||
|
|
@ -729,9 +687,7 @@
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"users_table_username_unique": {
|
"users_table_username_unique": {
|
||||||
"name": "users_table_username_unique",
|
"name": "users_table_username_unique",
|
||||||
"columns": [
|
"columns": ["username"],
|
||||||
"username"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -829,16 +785,12 @@
|
||||||
"indexes": {
|
"indexes": {
|
||||||
"volumes_table_short_id_unique": {
|
"volumes_table_short_id_unique": {
|
||||||
"name": "volumes_table_short_id_unique",
|
"name": "volumes_table_short_id_unique",
|
||||||
"columns": [
|
"columns": ["short_id"],
|
||||||
"short_id"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
},
|
},
|
||||||
"volumes_table_name_unique": {
|
"volumes_table_name_unique": {
|
||||||
"name": "volumes_table_name_unique",
|
"name": "volumes_table_name_unique",
|
||||||
"columns": [
|
"columns": ["name"],
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
"isUnique": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,7 @@ const disableTwoFactor = async (username: string): Promise<void> => {
|
||||||
console.log(" All existing sessions have been invalidated.");
|
console.log(" All existing sessions have been invalidated.");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const twoFactorCommand = new Command("2fa")
|
export const twoFactorCommand = new Command("2fa").description("Two-factor authentication recovery").addCommand(
|
||||||
.description("Two-factor authentication recovery")
|
|
||||||
.addCommand(
|
|
||||||
new Command("disable")
|
new Command("disable")
|
||||||
.description("Disable 2FA for a user (recovery method when authenticator access is lost)")
|
.description("Disable 2FA for a user (recovery method when authenticator access is lost)")
|
||||||
.requiredOption("-u, --username <username>", "Username of the account")
|
.requiredOption("-u, --username <username>", "Username of the account")
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { authService } from "../modules/auth/auth.service";
|
||||||
|
|
||||||
export class CleanupSessionsJob extends Job {
|
export class CleanupSessionsJob extends Job {
|
||||||
async run() {
|
async run() {
|
||||||
authService.cleanupExpiredSessions();
|
await authService.cleanupExpiredSessions();
|
||||||
authService.cleanupExpiredPending2faSessions();
|
authService.cleanupExpiredPending2faSessions();
|
||||||
|
|
||||||
return { done: true, timestamp: new Date() };
|
return { done: true, timestamp: new Date() };
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue