1
0
mirror of https://github.com/pocket-id/pocket-id.git synced 2026-02-12 13:51:18 +00:00

feat: add ability to send login code via email (#457)

Co-authored-by: Kyle Mendell <kmendell@ofkm.us>
This commit is contained in:
Elias Schneider
2025-04-20 18:32:40 +02:00
committed by GitHub
parent e571996cb5
commit fe1c4b18cd
22 changed files with 257 additions and 137 deletions

View File

@@ -9,8 +9,10 @@
import { Separator } from '$lib/components/ui/separator';
import { m } from '$lib/paraglide/messages';
import UserService from '$lib/services/user-service';
import appConfigStore from '$lib/stores/application-configuration-store';
import { axiosErrorToast } from '$lib/utils/error-util';
import { mode } from 'mode-watcher';
import { toast } from 'svelte-sonner';
let {
userId = $bindable()
@@ -32,7 +34,7 @@
[m.one_month()]: 60 * 60 * 24 * 30
};
async function createOneTimeAccessToken() {
async function createLoginCode() {
try {
const expiration = new Date(Date.now() + availableExpirations[selectedExpiration] * 1000);
code = await userService.createOneTimeAccessToken(expiration, userId!);
@@ -42,6 +44,17 @@
}
}
async function sendLoginCodeEmail() {
try {
const expiration = new Date(Date.now() + availableExpirations[selectedExpiration] * 1000);
await userService.requestOneTimeAccessEmailAsAdmin(userId!, expiration);
toast.success(m.login_code_email_success());
onOpenChange(false);
} catch (e) {
axiosErrorToast(e);
}
}
function onOpenChange(open: boolean) {
if (!open) {
oneTimeLink = null;
@@ -81,13 +94,20 @@
</Select.Content>
</Select.Root>
</div>
<Button
onclick={() => createOneTimeAccessToken()}
disabled={!selectedExpiration}
class="mt-2 w-full"
>
{m.generate_code()}
</Button>
<Dialog.Footer class="mt-2">
{#if $appConfigStore.emailOneTimeAccessAsAdminEnabled}
<Button
onclick={() => sendLoginCodeEmail()}
variant="secondary"
disabled={!selectedExpiration}
>
{m.send_email()}
</Button>
{/if}
<Button onclick={() => createLoginCode()} disabled={!selectedExpiration}
>{m.show_code()}</Button
>
</Dialog.Footer>
{:else}
<div class="flex flex-col items-center gap-2">
<CopyToClipboard value={code!}>

View File

@@ -87,10 +87,14 @@ export default class UserService extends APIService {
return res.data as User;
}
async requestOneTimeAccessEmail(email: string, redirectPath?: string) {
async requestOneTimeAccessEmailAsUnauthenticatedUser(email: string, redirectPath?: string) {
await this.api.post('/one-time-access-email', { email, redirectPath });
}
async requestOneTimeAccessEmailAsAdmin(userId: string, expiresAt: Date) {
await this.api.post(`/users/${userId}/one-time-access-email`, { expiresAt });
}
async updateUserGroups(id: string, userGroupIds: string[]) {
const res = await this.api.put(`/users/${id}/user-groups`, { userGroupIds });
return res.data as User;

View File

@@ -1,7 +1,8 @@
export type AppConfig = {
appName: string;
allowOwnAccountEdit: boolean;
emailOneTimeAccessEnabled: boolean;
emailOneTimeAccessAsUnauthenticatedEnabled: boolean;
emailOneTimeAccessAsAdminEnabled: boolean;
ldapEnabled: boolean;
disableAnimations: boolean;
};