Note: The page will be refreshed to apply the changes of "Email" or
"Display Name".
@@ -100,19 +118,37 @@ export default function UserSettings({ toggleSettingsModal }: Props) {
- {/*
@@ -164,21 +200,18 @@ export default function UserSettings({ toggleSettingsModal }: Props) {
you to additional collections in the box below, separated by spaces.
) : null}
- {stateIsTampered() ? (
-
- Apply Settings
-
- ) : null}
+
+ Apply Settings
+
);
}
diff --git a/lib/api/controllers/users/updateUser.ts b/lib/api/controllers/users/updateUser.ts
index b075afc..f719939 100644
--- a/lib/api/controllers/users/updateUser.ts
+++ b/lib/api/controllers/users/updateUser.ts
@@ -5,9 +5,38 @@
import { prisma } from "@/lib/api/db";
import { AccountSettings } from "@/types/global";
+import fs from "fs";
+import path from "path";
export default async function (user: AccountSettings, userId: number) {
- console.log(typeof user);
+ console.log(console.log(user.profilePic));
+
+ const profilePic = user.profilePic;
+
+ if (profilePic && profilePic !== "DELETE") {
+ if ((user?.profilePic?.length as number) < 1572864) {
+ try {
+ const filePath = path.join(
+ process.cwd(),
+ `data/uploads/avatar/${userId}.jpg`
+ );
+
+ const base64Data = profilePic.replace(/^data:image\/jpeg;base64,/, "");
+
+ fs.writeFile(filePath, base64Data, "base64", function (err) {
+ console.log(err);
+ });
+ } catch (err) {
+ console.log("Error saving image:", err);
+ }
+ } else {
+ console.log("A file larger than 1.5MB was uploaded.");
+ }
+ } else if (profilePic === "DELETE") {
+ fs.unlink(`data/uploads/avatar/${userId}.jpg`, (err) => {
+ if (err) console.log(err);
+ });
+ }
const updatedUser = await prisma.user.update({
where: {
@@ -19,13 +48,9 @@ export default async function (user: AccountSettings, userId: number) {
collectionProtection: user.collectionProtection,
whitelistedUsers: user.whitelistedUsers,
},
- select: {
- name: true,
- email: true,
- collectionProtection: true,
- whitelistedUsers: true,
- },
});
- return { response: updatedUser, status: 200 };
+ const { password, ...unsensitiveInfo } = updatedUser;
+
+ return { response: unsensitiveInfo, status: 200 };
}
diff --git a/lib/client/fileExists.ts b/lib/client/fileExists.ts
new file mode 100644
index 0000000..db145d3
--- /dev/null
+++ b/lib/client/fileExists.ts
@@ -0,0 +1,9 @@
+export default async function fileExists(fileUrl: string): Promise {
+ try {
+ const response = await fetch(fileUrl, { method: "HEAD" });
+ return response.ok;
+ } catch (error) {
+ console.error("Error checking file existence:", error);
+ return false;
+ }
+}
diff --git a/lib/client/getInitialData.ts b/lib/client/getInitialData.ts
index a0acd6e..15fd355 100644
--- a/lib/client/getInitialData.ts
+++ b/lib/client/getInitialData.ts
@@ -22,7 +22,7 @@ export default function () {
setCollections();
setTags();
setLinks();
- setAccount(data.user.email as string);
+ setAccount(data.user.email as string, data.user.id);
}
}, [status]);
}
diff --git a/lib/client/resizeImage.ts b/lib/client/resizeImage.ts
new file mode 100644
index 0000000..17cbe56
--- /dev/null
+++ b/lib/client/resizeImage.ts
@@ -0,0 +1,17 @@
+import Resizer from "react-image-file-resizer";
+
+export const resizeImage = (file: File): Promise =>
+ new Promise((resolve) => {
+ Resizer.imageFileResizer(
+ file,
+ 150, // target width
+ 150, // target height
+ "JPEG", // output format
+ 100, // quality
+ 0, // rotation
+ (uri: any) => {
+ resolve(uri as Blob);
+ },
+ "blob" // output type
+ );
+ });
diff --git a/package.json b/package.json
index 9d3a987..f5a8016 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"puppeteer-extra-plugin-stealth": "^2.11.2",
"react": "18.2.0",
"react-dom": "18.2.0",
+ "react-image-file-resizer": "^0.4.8",
"react-select": "^5.7.0",
"typescript": "4.9.4",
"zustand": "^4.3.3"
diff --git a/pages/api/avatar/[id].ts b/pages/api/avatar/[id].ts
new file mode 100644
index 0000000..ae85c21
--- /dev/null
+++ b/pages/api/avatar/[id].ts
@@ -0,0 +1,38 @@
+// Copyright (C) 2022-present Daniel31x13
+// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.
+// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License along with this program. If not, see .
+
+import type { NextApiRequest, NextApiResponse } from "next";
+import { getServerSession } from "next-auth/next";
+import { authOptions } from "pages/api/auth/[...nextauth]";
+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)
+ return res.status(401).json({ response: "You must be logged in." });
+
+ // TODO: If profile is private, hide it to other users...
+
+ const filePath = path.join(
+ process.cwd(),
+ `data/uploads/avatar/${req.query.id}.jpg`
+ );
+
+ console.log(filePath);
+ const file = fs.existsSync(filePath)
+ ? fs.readFileSync(filePath)
+ : "File not found.";
+
+ if (!fs.existsSync(filePath))
+ res.setHeader("Content-Type", "text/plain").status(404);
+ else res.setHeader("Content-Type", "image/jpeg").status(200);
+
+ return res.send(file);
+}
diff --git a/prisma/migrations/20230520142249_init/migration.sql b/prisma/migrations/20230522122002_init/migration.sql
similarity index 98%
rename from prisma/migrations/20230520142249_init/migration.sql
rename to prisma/migrations/20230522122002_init/migration.sql
index 6cb80d7..770d6a9 100644
--- a/prisma/migrations/20230520142249_init/migration.sql
+++ b/prisma/migrations/20230522122002_init/migration.sql
@@ -6,7 +6,6 @@ CREATE TABLE "User" (
"password" TEXT NOT NULL,
"collectionProtection" BOOLEAN NOT NULL DEFAULT false,
"whitelistedUsers" TEXT[] DEFAULT ARRAY[]::TEXT[],
- "profilePhotoPath" TEXT NOT NULL DEFAULT '',
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index e1c7e7f..5930434 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -22,7 +22,6 @@ model User {
collectionsJoined UsersAndCollections[]
collectionProtection Boolean @default(false)
whitelistedUsers String[] @default([])
- profilePhotoPath String @default("")
createdAt DateTime @default(now())
}
diff --git a/store/account.ts b/store/account.ts
index 5a0e3bb..3358ce6 100644
--- a/store/account.ts
+++ b/store/account.ts
@@ -9,20 +9,20 @@ import { AccountSettings } from "@/types/global";
type AccountStore = {
account: User;
- setAccount: (email: string) => void;
+ setAccount: (email: string, id: number) => void;
updateAccount: (user: AccountSettings) => Promise;
};
const useAccountStore = create()((set) => ({
account: {} as User,
- setAccount: async (email) => {
+ setAccount: async (email, id) => {
const response = await fetch(`/api/routes/users?email=${email}`);
const data = await response.json();
console.log(data);
- if (response.ok) set({ account: data.response });
+ if (response.ok) set({ account: { ...data.response } });
},
updateAccount: async (user) => {
const response = await fetch("/api/routes/users", {
diff --git a/types/global.ts b/types/global.ts
index 1200961..da3fff3 100644
--- a/types/global.ts
+++ b/types/global.ts
@@ -3,7 +3,8 @@
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program. If not, see .
-import { Collection, Link, Tag } from "@prisma/client";
+import { Collection, Link, Tag, User } from "@prisma/client";
+import { SetStateAction } from "react";
export interface ExtendedLink extends Link {
tags: Tag[];
@@ -58,9 +59,6 @@ export type SearchSettings = {
};
};
-export type AccountSettings = {
- name: string;
- email: string;
- collectionProtection: boolean;
- whitelistedUsers: string[];
-};
+export interface AccountSettings extends User {
+ profilePic: string | null;
+}
diff --git a/yarn.lock b/yarn.lock
index 6081366..65023ba 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3140,6 +3140,11 @@ react-dom@18.2.0:
loose-envify "^1.1.0"
scheduler "^0.23.0"
+react-image-file-resizer@^0.4.8:
+ version "0.4.8"
+ resolved "https://registry.yarnpkg.com/react-image-file-resizer/-/react-image-file-resizer-0.4.8.tgz#85f4ae4469fd2867d961568af660ef403d7a79af"
+ integrity sha512-Ue7CfKnSlsfJ//SKzxNMz8avDgDSpWQDOnTKOp/GNRFJv4dO9L5YGHNEnj40peWkXXAK2OK0eRIoXhOYpUzUTQ==
+
react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"