added the ability for the users to hide there profile
This commit is contained in:
parent
e774f41d37
commit
240d92aeae
|
@ -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 = {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -8,5 +8,7 @@ export default async function (email: string) {
|
|||
|
||||
const data = await response.json();
|
||||
|
||||
console.log(data);
|
||||
|
||||
return data.response;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
@ -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())
|
||||
}
|
||||
|
|
Ŝarĝante…
Reference in New Issue