Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion web/src/pages/UsersOverviewPage/UsersTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ export const UsersTable = () => {
device: Device,
username: string,
reservedDeviceNames: string[],
reservedPubkeys: string[],
): MenuItemsGroup[] => [
{
items: [
Expand All @@ -449,6 +450,7 @@ export const UsersTable = () => {
openModal(ModalName.EditUserDevice, {
device,
reservedNames: reservedDeviceNames,
reservedPubkeys,
username,
});
},
Expand Down Expand Up @@ -508,6 +510,7 @@ export const UsersTable = () => {
(row: Row<RowData>, isLast = false) => {
const username = row.original.username;
const reservedDeviceNames = row.original.devices.map((d) => d.name);
const reservedPubkeys = row.original.devices.map((d) => d.wireguard_pubkey);
return row.original.devices.map((device, deviceIndex) => {
const lastRow = isLast && deviceIndex === row.original.devices.length - 1;
const latestNetwork = orderBy(
Expand All @@ -523,7 +526,12 @@ export const UsersTable = () => {
const connectionDate = latestNetwork?.last_connected_at
? displayDate(latestNetwork.last_connected_at)
: neverConnected;
const menuItems = makeDeviceRowMenu(device, username, reservedDeviceNames);
const menuItems = makeDeviceRowMenu(
device,
username,
reservedDeviceNames,
reservedPubkeys,
);
return (
<TableRowContainer
className={clsx({ last: lastRow })}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export const ProfileAuthKeysTable = () => {
id: rowData.id,
name: rowData.name,
username,
reservedNames: mapped.map((k) => k.name),
});
},
},
Expand All @@ -198,7 +199,7 @@ export const ProfileAuthKeysTable = () => {
},
}),
],
[deleteAuthKey, username, writeToClipboard],
[deleteAuthKey, username, writeToClipboard, mapped.map],
Comment thread
jakub-tldr marked this conversation as resolved.
);

const table = useReactTable({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useStore } from '@tanstack/react-form';
import { useMutation } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import z from 'zod';
import { m } from '../../../../../../../paraglide/messages';
import api from '../../../../../../../shared/api/api';
Expand Down Expand Up @@ -50,11 +50,21 @@ export const RenameAuthKeyModal = () => {
);
};

const formSchema = z.object({
name: z.string().trim().min(1, m.form_error_required()),
});
const getFormSchema = (reservedNames: string[]) =>
z.object({
name: z
.string()
.trim()
.min(1, m.form_error_required())
.refine((val) => !reservedNames.includes(val), m.form_error_name_reserved()),
});

const ModalContent = ({ id, name, username, reservedNames }: OpenAuthKeyRenameModal) => {
const formSchema = useMemo(
() => getFormSchema(reservedNames.filter((n) => n !== name)),
[reservedNames, name],
);

const ModalContent = ({ id, name, username }: OpenAuthKeyRenameModal) => {
const { mutateAsync } = useMutation({
mutationFn: api.user.renameAuthKey,
meta: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ const DevicesTable = ({ rowData }: { rowData: RowData[] }) => {
const username = user.username;

const reservedNames = useMemo(() => rowData.map((row) => row.name), [rowData]);
const reservedPubkeys = useMemo(
() => rowData.map((row) => row.wireguard_pubkey),
[rowData],
);

const addDeviceProps = useMemo(
(): ButtonProps => ({
Expand Down Expand Up @@ -121,6 +125,7 @@ const DevicesTable = ({ rowData }: { rowData: RowData[] }) => {
openModal(ModalName.EditUserDevice, {
device: row,
reservedNames: reservedNames,
reservedPubkeys: reservedPubkeys,
username,
});
},
Expand Down Expand Up @@ -177,7 +182,7 @@ const DevicesTable = ({ rowData }: { rowData: RowData[] }) => {
);
return [{ items }];
},
[reservedNames, username, isAdmin],
[reservedNames, username, isAdmin, reservedPubkeys],
);

const tableColumns = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { formChangeLogic } from '../../../../../formLogic';
import './style.scss';
import { useStore } from '@tanstack/react-form';
import { useMutation } from '@tanstack/react-query';
import type { AxiosError } from 'axios';
import { useMemo } from 'react';
import api from '../../../../../api/api';
import type { ApiError } from '../../../../../api/types';
import { SizedBox } from '../../../../../defguard-ui/components/SizedBox/SizedBox';
import { ThemeSpacing } from '../../../../../defguard-ui/types';
import { patternValidWireguardKey } from '../../../../../patterns';
Expand Down Expand Up @@ -79,7 +81,7 @@ export const AddDeviceModalManualSetupStep = () => {
onSubmit: formSchema,
onChange: formSchema,
},
onSubmit: async ({ value }) => {
onSubmit: async ({ value, formApi }) => {
let publicKey: string;
let privateKey: string | undefined;

Expand All @@ -95,8 +97,21 @@ export const AddDeviceModalManualSetupStep = () => {
name: value.name,
username,
wireguard_pubkey: publicKey,
}).catch((e: AxiosError<ApiError>) => {
const msg = e.response?.data.msg;
if (msg?.includes('already exists')) {
formApi.setErrorMap({
onSubmit: {
fields: {
publicKey: m.form_error_key_exists(),
},
},
});
}
});

if (!createResponse) return;

if (!createResponse.data.configs.length) {
useAddUserDeviceModal.getState().close();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const EditUserDeviceModal = () => {
);
};

const getFormSchema = (names: string[]) =>
const getFormSchema = (names: string[], pubkeys: string[]) =>
z.object({
name: z
.string()
Expand All @@ -63,13 +63,23 @@ const getFormSchema = (names: string[]) =>
publicKey: z
.string()
.length(44, m.form_error_invalid())
.regex(patternValidWireguardKey, m.form_error_invalid()),
.regex(patternValidWireguardKey, m.form_error_invalid())
.refine((val) => !pubkeys.includes(val), m.form_error_key_exists()),
});

const ModalContent = ({ device, reservedNames, username }: OpenEditDeviceModal) => {
const ModalContent = ({
device,
reservedNames,
reservedPubkeys,
username,
}: OpenEditDeviceModal) => {
const formSchema = useMemo(
() => getFormSchema(reservedNames.filter((name) => name !== device.name)),
[reservedNames, device.name],
() =>
getFormSchema(
reservedNames.filter((name) => name !== device.name),
reservedPubkeys.filter((key) => key !== device.wireguard_pubkey),
),
[reservedNames, reservedPubkeys, device.name, device.wireguard_pubkey],
);

const { mutateAsync } = useMutation({
Expand Down
2 changes: 2 additions & 0 deletions web/src/shared/hooks/modalControls/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ export interface OpenConfirmActionModal {
export interface OpenEditDeviceModal {
device: Device;
reservedNames: string[];
reservedPubkeys: string[];
username: string;
}

export interface OpenAuthKeyRenameModal {
id: number;
name: string;
username: string;
reservedNames: string[];
}

export interface OpenAddApiTokenModal {
Expand Down
Loading