diff --git a/src/app/self-service/page.tsx b/src/app/self-service/page.tsx
index ee21330..b346443 100644
--- a/src/app/self-service/page.tsx
+++ b/src/app/self-service/page.tsx
@@ -1,12 +1,12 @@
"use client";
-import { aliasAvailable, changeOwnPassword, createAliasSelf, fetchOwnAliases } from "@/lib/actions";
+import { aliasAvailable, changeOwnPassword, createAliasSelf, deleteAlias, fetchOwnAliases } from "@/lib/actions";
import GhostMessage from "@/lib/components/ui/GhostMessage";
import LoadingSpinner from "@/lib/components/ui/LoadingSpinner";
import { AliasEntry } from "@/lib/db";
import useWindowDimensions from "@/lib/hooks/useWindowDimensions";
import { aliasesNeedApproval } from "@/lib/util";
-import { Card, Text, Heading, Flex, TextField, Button, IconButton, Popover, Link, Tabs, Box, Grid, Dialog, Callout, Tooltip, Table, ScrollArea, DropdownMenu } from "@radix-ui/themes";
+import { Card, Text, Heading, Flex, TextField, Button, IconButton, Popover, Link, Tabs, Box, Grid, Dialog, Callout, Tooltip, Table, ScrollArea, DropdownMenu, Code } from "@radix-ui/themes";
import { AlertCircleIcon, CheckIcon, ChevronDownIcon, CopyIcon, ExternalLinkIcon, InfoIcon, LockIcon, UserIcon, UsersRound } from "lucide-react";
import { useSession } from "next-auth/react";
import { useEffect, useState } from "react";
@@ -303,6 +303,7 @@ export default function SelfService() {
const alias = await createAliasSelf(`${newAliasUsername}@${newAliasDomain}`);
setAliases([...(aliases ?? []), alias]);
} catch(e) {
+ console.error(e);
alert(e);
}
}}>Change
@@ -332,7 +333,41 @@ export default function SelfService() {
{alias.alias}
{alias.pending ? "Pending" : "Active"}
-
+
+
+
+
+
+
+ Delete alias
+
+ Are you sure you want to delete the alias {alias.alias}
?
+ It will become available for other users to claim immediately.
+
+
+
+
+
+
+
+
+
+
+
+
))
}
diff --git a/src/lib/actions.ts b/src/lib/actions.ts
index 483f73d..8bf25b5 100644
--- a/src/lib/actions.ts
+++ b/src/lib/actions.ts
@@ -1,7 +1,7 @@
"use server";
import { getServerSession } from "next-auth";
-import { AliasEntry, createAlias, database, getUserAliases, setUserPassword } from "./db";
+import { AliasEntry, createAlias, database, deleteAliasEntry, getAlias, getUserAliases, setUserPassword } from "./db";
import { aliasesNeedApproval, isAdmin } from "./util";
export async function fetchAllUsers(): Promise {
@@ -66,3 +66,14 @@ export async function createAliasSelf(alias: string): Promise {
pending: pending
};
}
+
+export async function deleteAlias(alias: string) {
+ const session = await getServerSession();
+ if (!session?.user?.email) throw new Error("Unauthenticated");
+
+ if (!isAdmin(session) && (await getAlias(alias))?.address != session.user.email) {
+ throw new Error("Unauthorized");
+ }
+
+ await deleteAliasEntry(alias);
+}
diff --git a/src/lib/db.ts b/src/lib/db.ts
index 1f960e0..e20c0e2 100644
--- a/src/lib/db.ts
+++ b/src/lib/db.ts
@@ -77,6 +77,22 @@ export function getUserAliases(email: string) {
});
}
+export function getAlias(alias: string) {
+ return new Promise(async (resolve, reject) => {
+ const db = database('aliases');
+
+ db.get("SELECT id, address, alias, pending FROM aliases WHERE address = ?", alias, (err, res: AliasEntry) => {
+ db.close();
+ if (err) return reject(err);
+ if (!res) return resolve(undefined);
+ resolve({
+ ...res,
+ pending: !!res.pending,
+ });
+ });
+ });
+}
+
export function createAlias(user: string, alias: string, pending: boolean) {
return new Promise(async (resolve, reject) => {
const db = database('aliases');
@@ -95,3 +111,18 @@ export function createAlias(user: string, alias: string, pending: boolean) {
});
});
}
+
+export function deleteAliasEntry(alias: string) {
+ return new Promise(async (resolve, reject) => {
+ const db = database('aliases');
+
+ db.run(
+ "DELETE FROM aliases WHERE alias = ?",
+ alias,
+ function(err: any) {
+ db.close();
+ if (err) return reject(err);
+ resolve();
+ });
+ });
+}