added the ability for the users to hide there profile

This commit is contained in:
Daniel 2023-05-23 07:38:16 +03:30
parent e774f41d37
commit 240d92aeae
10 changed files with 94 additions and 34 deletions

View File

@ -10,6 +10,7 @@ import useCollectionStore from "@/store/collections";
import { NewCollection } from "@/types/global";
import { useSession } from "next-auth/react";
import RequiredBadge from "../RequiredBadge";
import getPublicUserDataByEmail from "@/lib/client/getPublicUserDataByEmail";
type Props = {
toggleCollectionModal: Function;
@ -36,14 +37,6 @@ export default function AddCollection({ toggleCollectionModal }: Props) {
if (response) toggleCollectionModal();
};
const getUserByEmail = async (email: string) => {
const response = await fetch(`/api/routes/users?email=${email}`);
const data = await response.json();
return data.response;
};
return (
<div className="flex flex-col gap-3 sm:w-[35rem] w-80">
<p className="text-xl text-sky-500 mb-2 text-center">New Collection</p>
@ -107,7 +100,7 @@ export default function AddCollection({ toggleCollectionModal }: Props) {
memberEmail.trim() !== ownerEmail
) {
// Lookup, get data/err, list ...
const user = await getUserByEmail(memberEmail.trim());
const user = await getPublicUserDataByEmail(memberEmail.trim());
if (user.email) {
const newMember = {

View File

@ -4,9 +4,7 @@
// You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
import React, { useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { AccountSettings } from "@/types/global";
import { faPenToSquare } from "@fortawesome/free-regular-svg-icons";
type Props = {
togglePasswordFormModal: Function;
@ -70,8 +68,7 @@ export default function AddCollection({
className="mx-auto mt-2 text-white flex items-center gap-2 py-2 px-5 rounded-md select-none font-bold duration-100 bg-sky-500 hover:bg-sky-400 cursor-pointer"
onClick={submit}
>
<FontAwesomeIcon icon={faPenToSquare} className="h-5" />
Change Password
Save
</div>
</div>
</div>

View File

@ -29,6 +29,9 @@ export default function UserSettings({ toggleSettingsModal }: Props) {
profilePic: null,
});
const [whitelistedUsersTextbox, setWhiteListedUsersTextbox] = useState(
user.whitelistedUsers.join(", ")
);
const [passwordFormModal, setPasswordFormModal] = useState(false);
const togglePasswordFormModal = () => {
@ -49,6 +52,21 @@ export default function UserSettings({ toggleSettingsModal }: Props) {
determineProfilePicSource();
}, []);
useEffect(() => {
setUser({
...user,
whitelistedUsers: stringToArray(whitelistedUsersTextbox),
});
}, [whitelistedUsersTextbox]);
const stringToArray = (str: string) => {
const stringWithoutSpaces = str.replace(/\s+/g, "");
const wordsArray = stringWithoutSpaces.split(",");
return wordsArray;
};
const handleImageUpload = async (e: any) => {
const file: File = e.target.files[0];
@ -77,6 +95,8 @@ export default function UserSettings({ toggleSettingsModal }: Props) {
};
const submit = async () => {
console.log(user);
await updateAccount({
...user,
profilePic:
@ -134,6 +154,14 @@ export default function UserSettings({ toggleSettingsModal }: Props) {
Change Password
</div>
</div>
{user.newPassword && user.oldPassword ? (
<p className="text-gray-500 text-sm mt-2">
Password modified. Please click{" "}
<span className=" whitespace-nowrap">"Apply Settings"</span> to
apply the changes..
</p>
) : null}
</div>
</div>
@ -204,23 +232,33 @@ export default function UserSettings({ toggleSettingsModal }: Props) {
<p className="text-sky-600">Privacy Settings</p>
<Checkbox
label="Limit who can add you to other Collections"
state={user.collectionProtection}
label="Make profile private"
state={user.isPrivate}
className="text-sm sm:text-base"
onClick={() =>
setUser({ ...user, collectionProtection: !user.collectionProtection })
}
onClick={() => setUser({ ...user, isPrivate: !user.isPrivate })}
/>
{user.collectionProtection ? (
<p className="text-gray-500 text-sm mb-3">
This will limit who can find and add you to other Collections.
</p>
{user.isPrivate ? (
<div>
<p className="text-sm font-bold text-sky-300 mb-2">
Whitelisted Users
</p>
<p className="text-gray-500 text-sm mb-3">
Please enter the email addresses of the users who are allowed to add
you to additional collections in the box below, separated by spaces.
Please provide the Email addresses of the users you wish to grant
visibility to your profile. Separate the addresses with a comma.
Users not included will be unable to view your profile.
</p>
<textarea
className="w-full resize-none border rounded-md duration-100 bg-white p-2 outline-none border-sky-100 focus:border-sky-500"
placeholder="No one can add you to any collections right now..."
placeholder="Your profile is hidden from everyone right now..."
value={whitelistedUsersTextbox}
onChange={(e) => {
setWhiteListedUsersTextbox(e.target.value);
}}
></textarea>
</div>
) : null}

View File

@ -5,14 +5,26 @@
import { prisma } from "@/lib/api/db";
export default async function (lookupEmail: string, isSelf: boolean) {
export default async function (
lookupEmail: string,
isSelf: boolean,
userEmail: string
) {
const user = await prisma.user.findUnique({
where: {
email: lookupEmail,
},
});
if (!user) return { response: "User not found." || null, status: 404 };
if (!user) return { response: "User not found.", status: 404 };
if (
!isSelf &&
user?.isPrivate &&
!user.whitelistedUsers.includes(userEmail)
) {
return { response: "This profile is private.", status: 401 };
}
const { password, ...unsensitiveInfo } = user;

View File

@ -44,7 +44,7 @@ export default async function (user: AccountSettings, userId: number) {
data: {
name: user.name,
email: user.email,
collectionProtection: user.collectionProtection,
isPrivate: user.isPrivate,
whitelistedUsers: user.whitelistedUsers,
},
});

View File

@ -8,5 +8,7 @@ export default async function (email: string) {
const data = await response.json();
console.log(data);
return data.response;
}

View File

@ -6,23 +6,41 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "pages/api/auth/[...nextauth]";
import { prisma } from "@/lib/api/db";
import path from "path";
import fs from "fs";
export default async function (req: NextApiRequest, res: NextApiResponse) {
if (!req.query.id)
return res.status(401).json({ response: "Invalid parameters." });
const session = await getServerSession(req, res, authOptions);
if (!session?.user?.email)
const userId = session?.user.id;
const userEmail = session?.user.email;
const queryId = Number(req.query.id);
if (!queryId)
return res.status(401).json({ response: "Invalid parameters." });
if (!userId || !userEmail)
return res.status(401).json({ response: "You must be logged in." });
// TODO: If profile is private, hide it to other users...
if (userId !== queryId) {
const targetUser = await prisma.user.findUnique({
where: {
id: queryId,
},
});
if (
targetUser?.isPrivate &&
!targetUser.whitelistedUsers.includes(userEmail)
) {
return res.status(401).json({ response: "This profile is private." });
}
}
const filePath = path.join(
process.cwd(),
`data/uploads/avatar/${req.query.id}.jpg`
`data/uploads/avatar/${queryId}.jpg`
);
console.log(filePath);

View File

@ -20,7 +20,7 @@ export default async function (req: NextApiRequest, res: NextApiResponse) {
const isSelf = session.user.email === lookupEmail ? true : false;
if (req.method === "GET") {
const users = await getUsers(lookupEmail, isSelf);
const users = await getUsers(lookupEmail, isSelf, session.user.email);
return res.status(users.status).json({ response: users.response });
} else if (req.method === "PUT" && !req.body.password) {
const updated = await updateUser(req.body, session.user.id);

View File

@ -4,7 +4,7 @@ CREATE TABLE "User" (
"name" TEXT NOT NULL,
"email" TEXT NOT NULL,
"password" TEXT NOT NULL,
"collectionProtection" BOOLEAN NOT NULL DEFAULT false,
"isPrivate" BOOLEAN NOT NULL DEFAULT false,
"whitelistedUsers" TEXT[] DEFAULT ARRAY[]::TEXT[],
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

View File

@ -20,7 +20,7 @@ model User {
collections Collection[]
tags Tag[]
collectionsJoined UsersAndCollections[]
collectionProtection Boolean @default(false)
isPrivate Boolean @default(false)
whitelistedUsers String[] @default([])
createdAt DateTime @default(now())
}