Skip to content

Commit

Permalink
feat(ui:profile) add profile card (prowler-cloud#5948)
Browse files Browse the repository at this point in the history
  • Loading branch information
paabloLC authored Nov 28, 2024
1 parent 4ba1c02 commit fd8d34e
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 49 deletions.
31 changes: 31 additions & 0 deletions ui/actions/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"use server";

import { revalidatePath } from "next/cache";
import { AuthError } from "next-auth";
import { z } from "zod";

import { signIn, signOut } from "@/auth.config";
import { auth } from "@/auth.config";
import { parseStringify } from "@/lib";
import { authFormSchema } from "@/types";

const formSchemaSignIn = authFormSchema("sign-in");
Expand Down Expand Up @@ -139,6 +142,34 @@ export const getToken = async (formData: z.infer<typeof formSchemaSignIn>) => {
}
};

export const getProfileInfo = async () => {
const session = await auth();
const keyServer = process.env.API_BASE_URL;
const url = new URL(`${keyServer}/users/me`);

try {
const response = await fetch(url.toString(), {
method: "GET",
headers: {
Accept: "application/vnd.api+json",
Authorization: `Bearer ${session?.accessToken}`,
},
});

if (!response.ok) {
throw new Error(`Failed to fetch user data: ${response.statusText}`);
}

const data = await response.json();
const parsedData = parseStringify(data);
revalidatePath("/profile");
return parsedData;
} catch (error) {
console.error("Error fetching profile:", error);
return undefined;
}
};

export const getUserByMe = async (accessToken: string) => {
const keyServer = process.env.API_BASE_URL;
const url = new URL(`${keyServer}/users/me`);
Expand Down
45 changes: 27 additions & 18 deletions ui/app/(prowler)/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
import { Spacer } from "@nextui-org/react";
import { redirect } from "next/navigation";
import React from "react";
import React, { Suspense } from "react";

// import { getUserByMe } from "@/actions/auth/auth";
import { auth } from "@/auth.config";
import { getProfileInfo } from "@/actions/auth";
import { Header } from "@/components/ui";
import { SkeletonUserInfo } from "@/components/users/profile";
import { UserInfo } from "@/components/users/profile/user-info";
import { UserProfileProps } from "@/types";

export default async function Profile() {
const session = await auth();

if (!session?.user) {
// redirect("/sign-in?returnTo=/profile");
redirect("/sign-in");
}

// const user = await getUserByMe();

return (
<>
<Header title="User Profile" icon="ci:users" />
<Spacer y={4} />
<Spacer y={6} />
<pre>{JSON.stringify(session.user, null, 2)}</pre>
<pre>{JSON.stringify(session.userId, null, 2)}</pre>
<pre>{JSON.stringify(session.tenantId, null, 2)}</pre>
<pre>{JSON.stringify(session, null, 2)}</pre>
<div className="min-h-screen">
<div className="container mx-auto space-y-8 px-0 py-6">
<div className="grid grid-cols-12 gap-6">
<div className="col-span-12 lg:col-span-3">
<Suspense fallback={<SkeletonUserInfo />}>
<SSRDataUser />
</Suspense>
</div>
</div>
</div>
</div>
</>
);
}

const SSRDataUser = async () => {
const userProfile: UserProfileProps = await getProfileInfo();

return (
<>
<h3 className="mb-4 text-sm font-bold">User Info</h3>
<UserInfo user={userProfile?.data} />
</>
);
};
32 changes: 1 addition & 31 deletions ui/components/filters/custom-region-selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,7 @@ import { Select, SelectItem } from "@nextui-org/react";
import { useRouter, useSearchParams } from "next/navigation";
import React, { useCallback, useMemo } from "react";

const regions = [
{ key: "af-south-1", label: "AF South 1" },
{ key: "ap-east-1", label: "AP East 1" },
{ key: "ap-northeast-1", label: "AP Northeast 1" },
{ key: "ap-northeast-2", label: "AP Northeast 2" },
{ key: "ap-northeast-3", label: "AP Northeast 3" },
{ key: "ap-south-1", label: "AP South 1" },
{ key: "ap-south-2", label: "AP South 2" },
{ key: "ap-southeast-1", label: "AP Southeast 1" },
{ key: "ap-southeast-2", label: "AP Southeast 2" },
{ key: "ap-southeast-3", label: "AP Southeast 3" },
{ key: "ap-southeast-4", label: "AP Southeast 4" },
{ key: "ca-central-1", label: "CA Central 1" },
{ key: "ca-west-1", label: "CA West 1" },
{ key: "eu-central-1", label: "EU Central 1" },
{ key: "eu-central-2", label: "EU Central 2" },
{ key: "eu-north-1", label: "EU North 1" },
{ key: "eu-south-1", label: "EU South 1" },
{ key: "eu-south-2", label: "EU South 2" },
{ key: "eu-west-1", label: "EU West 1" },
{ key: "eu-west-2", label: "EU West 2" },
{ key: "eu-west-3", label: "EU West 3" },
{ key: "il-central-1", label: "IL Central 1" },
{ key: "me-central-1", label: "ME Central 1" },
{ key: "me-south-1", label: "ME South 1" },
{ key: "sa-east-1", label: "SA East 1" },
{ key: "us-east-1", label: "US East 1" },
{ key: "us-east-2", label: "US East 2" },
{ key: "us-west-1", label: "US West 1" },
{ key: "us-west-2", label: "US West 2" },
];
import { regions } from "@/lib/helper";

export const CustomRegionSelection: React.FC = () => {
const router = useRouter();
Expand Down
2 changes: 2 additions & 0 deletions ui/components/users/profile/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./skeleton-user-info";
export * from "./user-info";
64 changes: 64 additions & 0 deletions ui/components/users/profile/skeleton-user-info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Card, CardBody, CardHeader, Skeleton } from "@nextui-org/react";

export const SkeletonUserInfo = () => {
const rows = 4;

return (
<Card>
<CardHeader>
<Skeleton className="h-6 w-1/3 rounded-lg">
<div className="h-6 bg-default-200"></div>
</Skeleton>
</CardHeader>
<CardBody>
<div className="grid grid-cols-1 gap-4">
{/* Header Skeleton */}
<div className="grid grid-cols-4 border-b pb-2 text-sm font-semibold">
<Skeleton className="h-5 w-full rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
<Skeleton className="h-5 w-full rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
<Skeleton className="h-5 w-full rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
<Skeleton className="h-5 w-full rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
</div>

{/* Row Skeletons */}
{Array.from({ length: rows }).map((_, index) => (
<div
key={index}
className="grid grid-cols-4 items-center border-b py-2 text-sm"
>
{/* Provider Name */}
<div className="flex items-center space-x-2">
<Skeleton className="h-5 w-5 rounded-lg">
<div className="h-5 w-5 bg-default-200"></div>
</Skeleton>
<Skeleton className="h-5 w-1/3 rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
</div>
{/* Percent Passing */}
<Skeleton className="h-5 w-1/4 rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
{/* Failing Checks */}
<Skeleton className="h-5 w-1/4 rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
{/* Total Resources */}
<Skeleton className="h-5 w-1/4 rounded-lg">
<div className="h-5 bg-default-200"></div>
</Skeleton>
</div>
))}
</div>
</CardBody>
</Card>
);
};
77 changes: 77 additions & 0 deletions ui/components/users/profile/user-info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"use client";

import { Card, CardBody } from "@nextui-org/react";

import { DateWithTime } from "@/components/ui/entities";
import { UserProfileProps } from "@/types";

export const UserInfo = ({
user,
}: {
user: UserProfileProps["data"] | null;
}) => {
if (!user || !user.attributes) {
return (
<Card className="dark:bg-prowler-blue-400">
<CardBody>
<div className="space-y-3">
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">Name:</p>
<span className="text-sm">-</span>
</div>
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">Email:</p>
<span className="text-sm">-</span>
</div>
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">Company:</p>
<span className="text-sm">-</span>
</div>
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">
Date Joined:
</p>
<span className="text-sm">-</span>
</div>
</div>
<div className="mt-4 text-center text-sm text-red-600">
Unable to load user information.
<br />
Please check your API connection.
</div>
</CardBody>
</Card>
);
}

const { name, email, company_name, date_joined } = user.attributes;

return (
<Card className="dark:bg-prowler-blue-400">
<CardBody>
<div className="space-y-3">
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">Name:</p>
<span className="text-sm">{name}</span>
</div>
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">Email:</p>
<span className="text-sm">{email}</span>
</div>
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">Company:</p>
<span className="text-sm">{company_name}</span>
</div>
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-default-600">
Date Joined:
</p>
<span className="text-sm">
<DateWithTime inline dateTime={date_joined} />
</span>
</div>
</div>
</CardBody>
</Card>
);
};
94 changes: 94 additions & 0 deletions ui/lib/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,97 @@ export const getErrorMessage = async (error: unknown): Promise<string> => {
}
return message;
};

export const regions = [
// AWS Regions (ordered by usage)
{ key: "us-east-1", label: "AWS - US East 1" },
{ key: "us-west-1", label: "AWS - US West 1" },
{ key: "us-west-2", label: "AWS - US West 2" },
{ key: "eu-west-1", label: "AWS - EU West 1" },
{ key: "eu-central-1", label: "AWS - EU Central 1" },
{ key: "ap-southeast-1", label: "AWS - AP Southeast 1" },
{ key: "ap-northeast-1", label: "AWS - AP Northeast 1" },
{ key: "ap-southeast-2", label: "AWS - AP Southeast 2" },
{ key: "ca-central-1", label: "AWS - CA Central 1" },
{ key: "sa-east-1", label: "AWS - SA East 1" },
{ key: "af-south-1", label: "AWS - AF South 1" },
{ key: "ap-east-1", label: "AWS - AP East 1" },
{ key: "ap-northeast-2", label: "AWS - AP Northeast 2" },
{ key: "ap-northeast-3", label: "AWS - AP Northeast 3" },
{ key: "ap-south-1", label: "AWS - AP South 1" },
{ key: "ap-south-2", label: "AWS - AP South 2" },
{ key: "ap-southeast-3", label: "AWS - AP Southeast 3" },
{ key: "ap-southeast-4", label: "AWS - AP Southeast 4" },
{ key: "ca-west-1", label: "AWS - CA West 1" },
{ key: "eu-central-2", label: "AWS - EU Central 2" },
{ key: "eu-north-1", label: "AWS - EU North 1" },
{ key: "eu-south-1", label: "AWS - EU South 1" },
{ key: "eu-south-2", label: "AWS - EU South 2" },
{ key: "eu-west-2", label: "AWS - EU West 2" },
{ key: "eu-west-3", label: "AWS - EU West 3" },
{ key: "il-central-1", label: "AWS - IL Central 1" },
{ key: "me-central-1", label: "AWS - ME Central 1" },
{ key: "me-south-1", label: "AWS - ME South 1" },

// Azure Regions (ordered by usage)
{ key: "eastus", label: "Azure - East US" },
{ key: "eastus2", label: "Azure - East US 2" },
{ key: "westeurope", label: "Azure - West Europe" },
{ key: "southeastasia", label: "Azure - Southeast Asia" },
{ key: "uksouth", label: "Azure - UK South" },
{ key: "northeurope", label: "Azure - North Europe" },
{ key: "centralus", label: "Azure - Central US" },
{ key: "westus2", label: "Azure - West US 2" },
{ key: "southcentralus", label: "Azure - South Central US" },
{ key: "australiaeast", label: "Azure - Australia East" },
{ key: "canadacentral", label: "Azure - Canada Central" },
{ key: "japaneast", label: "Azure - Japan East" },
{ key: "koreacentral", label: "Azure - Korea Central" },
{ key: "southafricanorth", label: "Azure - South Africa North" },
{ key: "brazilsouth", label: "Azure - Brazil South" },
{ key: "francecentral", label: "Azure - France Central" },
{ key: "germanywestcentral", label: "Azure - Germany West Central" },
{ key: "switzerlandnorth", label: "Azure - Switzerland North" },
{ key: "uaenorth", label: "Azure - UAE North" },
// Remaining Azure Regions (less frequently used)
{ key: "westus", label: "Azure - West US" },
{ key: "northcentralus", label: "Azure - North Central US" },
{ key: "australiasoutheast", label: "Azure - Australia Southeast" },
{ key: "southindia", label: "Azure - South India" },
{ key: "westindia", label: "Azure - West India" },
{ key: "canadaeast", label: "Azure - Canada East" },
{ key: "francesouth", label: "Azure - France South" },
{ key: "norwayeast", label: "Azure - Norway East" },
{ key: "switzerlandwest", label: "Azure - Switzerland West" },
{ key: "ukwest", label: "Azure - UK West" },
{ key: "uaecentral", label: "Azure - UAE Central" },
{ key: "brazilsoutheast", label: "Azure - Brazil Southeast" },

// GCP Regions (ordered by usage)
{ key: "us-central1", label: "GCP - US Central (Iowa)" },
{ key: "us-east1", label: "GCP - US East (South Carolina)" },
{ key: "us-west1", label: "GCP - US West (Oregon)" },
{ key: "europe-west1", label: "GCP - Europe West (Belgium)" },
{ key: "asia-east1", label: "GCP - Asia East (Taiwan)" },
{ key: "asia-northeast1", label: "GCP - Asia Northeast (Tokyo)" },
{ key: "europe-west2", label: "GCP - Europe West (London)" },
{ key: "europe-west3", label: "GCP - Europe West (Frankfurt)" },
{ key: "europe-west4", label: "GCP - Europe West (Netherlands)" },
{ key: "asia-southeast1", label: "GCP - Asia Southeast (Singapore)" },
{ key: "australia-southeast1", label: "GCP - Australia Southeast (Sydney)" },
{
key: "northamerica-northeast1",
label: "GCP - North America Northeast (Montreal)",
},
// Remaining GCP Regions
{ key: "asia-east2", label: "GCP - Asia East (Hong Kong)" },
{ key: "asia-northeast2", label: "GCP - Asia Northeast (Osaka)" },
{ key: "asia-northeast3", label: "GCP - Asia Northeast (Seoul)" },
{ key: "asia-south1", label: "GCP - Asia South (Mumbai)" },
{ key: "asia-southeast2", label: "GCP - Asia Southeast (Jakarta)" },
{ key: "europe-north1", label: "GCP - Europe North (Finland)" },
{ key: "europe-west6", label: "GCP - Europe West (Zurich)" },
{ key: "southamerica-east1", label: "GCP - South America East (São Paulo)" },
{ key: "us-west2", label: "GCP - US West (Los Angeles)" },
{ key: "us-east4", label: "GCP - US East (Northern Virginia)" },
];
Loading

0 comments on commit fd8d34e

Please sign in to comment.