alias management for users

This commit is contained in:
Lea 2024-01-18 16:12:07 +01:00
parent c9aacdaf6a
commit 21405f9d1d
Signed by: Lea
GPG key ID: 1BAFFE8347019C42
4 changed files with 83 additions and 4 deletions

View file

@ -1,7 +1,7 @@
"use server";
import { getServerSession } from "next-auth";
import { AliasEntry, approveAliasEntry, createAlias, createUserEntry, database, deleteAliasEntry, getAlias, getAllAliases, getUserAliases, setUserPassword } from "./db";
import { AliasEntry, approveAliasEntry, createAliasEntry, createUserEntry, database, deleteAliasEntry, getAlias, getAllAliases, getUserAliases, setUserPassword } from "./db";
import { aliasesNeedApproval, isAdmin } from "./util";
export async function fetchAllUsers(): Promise<string[]> {
@ -68,13 +68,29 @@ export async function aliasAvailable(email: string) {
});
}
export async function createAlias(user: string, alias: string): Promise<AliasEntry> {
const session = await getServerSession();
if (!session?.user?.email) throw new Error("Unauthenticated");
if (!isAdmin(session)) throw new Error("Unauthenticated");
if (!await aliasAvailable(alias)) throw new Error("Alias unavailable");
const id = await createAliasEntry(user, alias.toLowerCase(), false);
return {
id: id,
address: session.user.email,
alias: alias,
pending: false
};
}
export async function createAliasSelf(alias: string): Promise<AliasEntry> {
const session = await getServerSession();
if (!session?.user?.email) throw new Error("Unauthenticated");
const pending = aliasesNeedApproval(session);
if (!await aliasAvailable(alias)) throw new Error("Alias unavailable");
const id = await createAlias(session.user.email, alias.toLowerCase(), pending);
const id = await createAliasEntry(session.user.email, alias.toLowerCase(), pending);
return {
id: id,

View file

@ -0,0 +1,59 @@
import { createAlias } from "@/lib/actions";
import { AliasEntry } from "@/lib/db";
import { Button, Callout, Dialog, Flex, TextField } from "@radix-ui/themes";
import { AtSignIcon, MailWarningIcon } from "lucide-react";
import { useState } from "react";
export default function CreateAliasButton({ user, onCreate }: { user: string, onCreate?: (alias: AliasEntry) => any }) {
const [value, setValue] = useState("");
return (
<Dialog.Root onOpenChange={(open) => !open && setValue("")}>
<Dialog.Trigger>
<Button variant="outline" size="1">Add alias</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title>Create alias</Dialog.Title>
<Callout.Root mb="4">
<Callout.Icon>
<MailWarningIcon />
</Callout.Icon>
<Callout.Text>Make sure the alias uses a valid domain!</Callout.Text>
</Callout.Root>
<TextField.Root>
<TextField.Slot>
<AtSignIcon size="16" />
</TextField.Slot>
<TextField.Input
placeholder={`${user.split("@")[0]}@alias.domain`}
value={value}
onChange={(e) => setValue(e.currentTarget.value.toLowerCase())}
/>
</TextField.Root>
<Flex gap="3" mt="4" justify="end">
<Dialog.Close>
<Button variant="surface">Cancel</Button>
</Dialog.Close>
<Dialog.Close>
<Button
variant="surface"
disabled={!value.includes("@")}
onClick={async () => {
try {
const alias = await createAlias(user, value);
onCreate?.(alias);
} catch (e) {
console.error(e);
alert(e);
}
}}
>Create</Button>
</Dialog.Close>
</Flex>
</Dialog.Content>
</Dialog.Root>
);
}

View file

@ -10,6 +10,7 @@ import { BananaIcon } from "lucide-react";
import LoadingSpinner from "../LoadingSpinner";
import { approveAlias, deleteAlias, fetchUserAliases } from "@/lib/actions";
import GenericConfirmationDialog from "../GenericConfirmationDialog";
import CreateAliasButton from "./CreateAliasButton";
export default function ManageUserButton({ email }: { email: string }) {
const [aliases, setAliases] = useState<AliasEntry[] | null>(null);
@ -44,7 +45,10 @@ export default function ManageUserButton({ email }: { email: string }) {
</Card>
<Card className="h-fit min-w-40">
<Heading size="3" mb="4">Aliases</Heading>
<Flex mb="4" justify="between">
<Heading size="3">Aliases</Heading>
<CreateAliasButton user={email} onCreate={(alias) => setAliases([...(aliases ?? []), alias])} />
</Flex>
{
aliases

View file

@ -121,7 +121,7 @@ export function getAlias(alias: string) {
});
}
export function createAlias(user: string, alias: string, pending: boolean) {
export function createAliasEntry(user: string, alias: string, pending: boolean) {
return new Promise<number>(async (resolve, reject) => {
const db = database('aliases');