瀏覽代碼

Remove dangerous logging

Owen Schwartz 6 月之前
父節點
當前提交
1361b47ef7

+ 1 - 0
server/auth/actions.ts

@@ -10,6 +10,7 @@ export enum ActionsEnum {
     // deleteOrg = "deleteOrg",
     getOrg = "getOrg",
     updateOrg = "updateOrg",
+    deleteOrg = "deleteOrg",
     createSite = "createSite",
     deleteSite = "deleteSite",
     getSite = "getSite",

+ 0 - 1
server/middlewares/verifySiteAccess.ts

@@ -29,7 +29,6 @@ export async function verifySiteAccess(
     }
 
     if (isNaN(siteId)) {
-        logger.debug(JSON.stringify(req.body));
         return next(createHttpError(HttpCode.BAD_REQUEST, "Invalid site ID"));
     }
 

+ 0 - 2
server/routers/auth/login.ts

@@ -126,8 +126,6 @@ export async function login(
         await createSession(token, existingUser.userId);
         const cookie = serializeSessionCookie(token);
 
-        logger.debug(cookie);
-
         res.appendHeader("Set-Cookie", cookie);
 
         if (

+ 0 - 2
server/routers/auth/requestPasswordReset.ts

@@ -75,8 +75,6 @@ export async function requestPasswordReset(
         // TODO: send email with link to reset password on dashboard
         // something like: https://example.com/auth/reset-password?email=${email}&?token=${token}
         // for now, just log the token
-        logger.debug(`Password reset token: ${token}`);
-
         return response<RequestPasswordResetResponse>(res, {
             data: {
                 sentEmail: true,

+ 70 - 20
server/routers/org/deleteOrg.ts

@@ -1,7 +1,13 @@
 import { Request, Response, NextFunction } from "express";
 import { z } from "zod";
 import { db } from "@server/db";
-import { orgs, userActions } from "@server/db/schema";
+import {
+    newts,
+    newtSessions,
+    orgs,
+    sites,
+    userActions
+} from "@server/db/schema";
 import { eq } from "drizzle-orm";
 import response from "@server/utils/response";
 import HttpCode from "@server/types/HttpCode";
@@ -9,9 +15,11 @@ import createHttpError from "http-errors";
 import { ActionsEnum, checkUserActionPermission } from "@server/auth/actions";
 import logger from "@server/logger";
 import { fromError } from "zod-validation-error";
+import { sendToClient } from "../ws";
+import { deletePeer } from "../gerbil/peers";
 
 const deleteOrgSchema = z.object({
-    orgId: z.string(),
+    orgId: z.string()
 });
 
 export async function deleteOrg(
@@ -32,26 +40,27 @@ export async function deleteOrg(
 
         const { orgId } = parsedParams.data;
 
-        // // Check if the user has permission to list sites
-        // const hasPermission = await checkUserActionPermission(
-        //     ActionsEnum.deleteOrg,
-        //     req
-        // );
-        // if (!hasPermission) {
-        //     return next(
-        //         createHttpError(
-        //             HttpCode.FORBIDDEN,
-        //             "User does not have permission to perform this action"
-        //         )
-        //     );
-        // }
+        // Check if the user has permission to list sites
+        const hasPermission = await checkUserActionPermission(
+            ActionsEnum.deleteOrg,
+            req
+        );
+        if (!hasPermission) {
+            return next(
+                createHttpError(
+                    HttpCode.FORBIDDEN,
+                    "User does not have permission to perform this action"
+                )
+            );
+        }
 
-        const deletedOrg = await db
-            .delete(orgs)
+        const [org] = await db
+            .select()
+            .from(orgs)
             .where(eq(orgs.orgId, orgId))
-            .returning();
+            .limit(1);
 
-        if (deletedOrg.length === 0) {
+        if (!org) {
             return next(
                 createHttpError(
                     HttpCode.NOT_FOUND,
@@ -60,12 +69,53 @@ export async function deleteOrg(
             );
         }
 
+        // we need to handle deleting each site
+        const orgSites = await db
+            .select()
+            .from(sites)
+            .where(eq(sites.orgId, orgId))
+            .limit(1);
+
+        if (sites) {
+            for (const site of orgSites) {
+                if (site.pubKey) {
+                    if (site.type == "wireguard") {
+                        await deletePeer(site.exitNodeId!, site.pubKey);
+                    } else if (site.type == "newt") {
+                        // get the newt on the site by querying the newt table for siteId
+                        const [deletedNewt] = await db
+                            .delete(newts)
+                            .where(eq(newts.siteId, site.siteId))
+                            .returning();
+                        if (deletedNewt) {
+                            const payload = {
+                                type: `newt/terminate`,
+                                data: {}
+                            };
+                            sendToClient(deletedNewt.newtId, payload);
+
+                            // delete all of the sessions for the newt
+                            db.delete(newtSessions)
+                                .where(
+                                    eq(newtSessions.newtId, deletedNewt.newtId)
+                                )
+                                .run();
+                        }
+                    }
+                }
+
+                db.delete(sites).where(eq(sites.siteId, site.siteId)).run();
+            }
+        }
+
+        await db.delete(orgs).where(eq(orgs.orgId, orgId)).returning();
+
         return response(res, {
             data: null,
             success: true,
             error: false,
             message: "Organization deleted successfully",
-            status: HttpCode.OK,
+            status: HttpCode.OK
         });
     } catch (error) {
         logger.error(error);

+ 1 - 1
server/routers/org/updateOrg.ts

@@ -16,7 +16,7 @@ const updateOrgParamsSchema = z.object({
 const updateOrgBodySchema = z
     .object({
         name: z.string().min(1).max(255).optional(),
-        domain: z.string().min(1).max(255).optional(),
+        // domain: z.string().min(1).max(255).optional(),
     })
     .strict()
     .refine((data) => Object.keys(data).length > 0, {

+ 0 - 1
server/routers/resource/authWithAccessToken.ts

@@ -104,7 +104,6 @@ export async function authWithAccessToken(
         //     outputLen: 32,
         //     parallelism: 1
         // });
-        logger.debug(`${accessToken} ${tokenItem.tokenHash}`)
         const validCode = accessToken === tokenItem.tokenHash;
 
         if (!validCode) {

+ 118 - 9
src/app/[orgId]/settings/general/page.tsx

@@ -4,16 +4,85 @@ import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog";
 import { Button } from "@app/components/ui/button";
 import { useOrgContext } from "@app/hooks/useOrgContext";
 import { userOrgUserContext } from "@app/hooks/useOrgUserContext";
+import { useToast } from "@app/hooks/useToast";
 import { useState } from "react";
+import {
+    Form,
+    FormControl,
+    FormDescription,
+    FormField,
+    FormItem,
+    FormLabel,
+    FormMessage
+} from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
+import { z } from "zod";
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { createApiClient } from "@app/api";
+import { useEnvContext } from "@app/hooks/useEnvContext";
+import { formatAxiosError } from "@app/lib/utils";
+import { AlertTriangle, Trash2 } from "lucide-react";
+import {
+    Card,
+    CardContent,
+    CardFooter,
+    CardHeader,
+    CardTitle
+} from "@/components/ui/card";
+
+const GeneralFormSchema = z.object({
+    name: z.string()
+});
+
+type GeneralFormValues = z.infer<typeof GeneralFormSchema>;
 
 export default function GeneralPage() {
     const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
 
     const { orgUser } = userOrgUserContext();
     const { org } = useOrgContext();
+    const { toast } = useToast();
+    const api = createApiClient(useEnvContext());
+
+    const form = useForm<GeneralFormValues>({
+        resolver: zodResolver(GeneralFormSchema),
+        defaultValues: {
+            name: org?.org.name
+        },
+        mode: "onChange"
+    });
 
     async function deleteOrg() {
-        console.log("not implemented");
+        await api
+            .delete(`/org/${org?.org.orgId}`)
+            .catch((e) => {
+                toast({
+                    variant: "destructive",
+                    title: "Failed to delete org",
+                    description: formatAxiosError(
+                        e,
+                        "An error occurred while deleting the org."
+                    ),
+                });
+            });
+    }
+
+    async function onSubmit(data: GeneralFormValues) {
+        await api
+            .post(`/org/${org?.org.orgId}`, {
+                name: data.name
+            })
+            .catch((e) => {
+                toast({
+                    variant: "destructive",
+                    title: "Failed to update org",
+                    description: formatAxiosError(
+                        e,
+                        "An error occurred while updating the org."
+                    )
+                });
+            });
     }
 
     return (
@@ -46,15 +115,55 @@ export default function GeneralPage() {
                 title="Delete organization"
             />
 
-            <div className="space-y-8">
-                {orgUser.isOwner ? (
-                    <Button onClick={() => setIsDeleteModalOpen(true)}>
-                        Delete Organization
+            <Form {...form}>
+                <form
+                    onSubmit={form.handleSubmit(onSubmit)}
+                    className="space-y-8 max-w-lg"
+                >
+                    <FormField
+                        control={form.control}
+                        name="name"
+                        render={({ field }) => (
+                            <FormItem>
+                                <FormLabel>Name</FormLabel>
+                                <FormControl>
+                                    <Input {...field} />
+                                </FormControl>
+                                <FormDescription>
+                                    This is the display name of the org
+                                </FormDescription>
+                                <FormMessage />
+                            </FormItem>
+                        )}
+                    />
+                    <Button type="submit">Save Changes</Button>
+                </form>
+            </Form>
+
+            <Card className="max-w-lg border-red-900 mt-5">
+                <CardHeader>
+                    <CardTitle className="flex items-center gap-2 text-red-600">
+                        <AlertTriangle className="h-5 w-5" />
+                        Danger Zone
+                    </CardTitle>
+                </CardHeader>
+                <CardContent>
+                    <p className="text-sm mb-4">
+                        Once you delete this org, there is no going back. Please
+                        be certain.
+                    </p>
+                </CardContent>
+                <CardFooter className="flex justify-end gap-2">
+                    <Button
+                        variant="destructive"
+                        onClick={() => setIsDeleteModalOpen(true)}
+                        className="flex items-center gap-2"
+                    >
+                        <Trash2 className="h-4 w-4" />
+                        Delete
                     </Button>
-                ) : (
-                    <p>Nothing to see here</p>
-                )}
-            </div>
+                </CardFooter>
+            </Card>
         </>
     );
 }