From 69697b54b1f4d8e1c61f6d9e606d964570f14d79 Mon Sep 17 00:00:00 2001 From: Akif9748 Date: Fri, 9 Sep 2022 16:29:36 +0300 Subject: [PATCH] Added avatar upload --- .gitignore | 8 +- APIDOCS.md | 1 + README.md | 4 +- index.js | 15 +- models/User.js | 2 +- package-lock.json | 251 +++++++++++++++++++++++++++++- package.json | 3 +- public/images/avatars/default.jpg | Bin 0 -> 5453 bytes routes/api/routes/users.js | 23 ++- routes/users.js | 12 +- views/avatar_upload.ejs | 30 ++++ views/edit_user.ejs | 53 ------- views/messages.ejs | 2 +- views/thread.ejs | 2 +- views/user.ejs | 1 + 15 files changed, 323 insertions(+), 84 deletions(-) create mode 100644 public/images/avatars/default.jpg create mode 100644 views/avatar_upload.ejs delete mode 100644 views/edit_user.ejs diff --git a/.gitignore b/.gitignore index 4d2b33e..0ef53cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ # Dependency directories node_modules/ -# env +# Environment variables .env # Test files -test.js \ No newline at end of file +test.js + +# avatars folder +public/images/avatars/* +!public/images/avatars/default.jpg \ No newline at end of file diff --git a/APIDOCS.md b/APIDOCS.md index 9ecb3b7..7abba2a 100644 --- a/APIDOCS.md +++ b/APIDOCS.md @@ -28,6 +28,7 @@ But in front end, the API will works with session. - GET `/api/users/:id` for fetch user. - DELETE `/api/users/:id/` for delete user. - PATCH `/api/users/:id/` for edit user. +- PUT `/api/users/:id/` for add profile photo to user. - GET `/api/threads/:id` for fetch thread. - DELETE `/api/threads/:id/` for delete thread. diff --git a/README.md b/README.md index daedbad..93b1ae2 100644 --- a/README.md +++ b/README.md @@ -32,15 +32,15 @@ Akf-forum has got an API for AJAX (fetch), other clients etc. And, you can learn ## TO-DO list | To do | Is done? | Priority | | ----- | -------- | -------- | +| Local pfp store | 🟢 | MEDIUM | | Page support for search | 🟡 | LOW | -| Local pfp store | 🔴 | MEDIUM | | IPs of users will add SecretModel | 🔴 | MEDIUM | | Category | ⚪ | MEDIUM | | Profile Message | 🔴 | LOW | | Last seen, last seen info | 🔴 | LOW | | Better Auth | 🔴 | MEDIUM | - Fix footer, theme - +- Navbar manuel select ## Major Version History - V4: Caching - V3: New Theme diff --git a/index.js b/index.js index 9541f3b..b37e510 100644 --- a/index.js +++ b/index.js @@ -7,24 +7,11 @@ const { def_theme, forum_name, desp } = require("./config.json"), port = process.env.PORT || 3000, mongoose = require("mongoose"), express = require('express'), - // multer = require("multer"), fs = require("fs"), app = express(); app.ips = []; -//Upload file -/* -const storage = multer.diskStorage({ - destination: function (req, file, cb) { - cb(null, "public/data"); - }, - filename: function (req, file, cb) { - const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); - cb(null, file.fieldname + "-" + uniqueSuffix + ".png"); - }, -}); -const upload = multer({ storage: storage }); -app.post("/stats", upload.single("uploaded_file"),*/ + require("dotenv").config(); mongoose.connect(process.env.MONGO_DB_URL, async () => console.log("Database is connected with", (app.ips = await BanModel.find({})).length, "banned IPs")); diff --git a/models/User.js b/models/User.js index 3232635..3805b9f 100644 --- a/models/User.js +++ b/models/User.js @@ -4,7 +4,7 @@ const schema = new mongoose.Schema({ id: { type: String }, name: String, - avatar: { type: String, default: "/images/guest.png" }, + avatar: { type: String, default: "/images/avatars/default.jpg" }, time: { type: Date, default: Date.now }, deleted: { type: Boolean, default: false }, edited: { type: Boolean, default: false }, diff --git a/package-lock.json b/package-lock.json index 51d77e4..49bcc66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,8 @@ "express-ip-block": "^0.1.2", "express-rate-limit": "^6.5.1", "express-session": "^1.17.2", - "mongoose": "^6.5.1" + "mongoose": "^6.5.1", + "multer": "^1.4.5-lts.1" }, "engines": { "node": ">=16" @@ -132,6 +133,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -262,6 +268,22 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -334,6 +356,47 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -371,6 +434,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -833,6 +901,11 @@ "node": ">=8" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/jake": { "version": "10.8.5", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", @@ -956,6 +1029,11 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, "node_modules/minipass": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", @@ -1087,6 +1165,34 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -1227,6 +1333,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1482,6 +1593,14 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -1572,6 +1691,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -1645,6 +1769,14 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -1737,6 +1869,11 @@ "color-convert": "^2.0.1" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -1825,6 +1962,19 @@ "ieee754": "^1.1.13" } }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1876,6 +2026,46 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -1904,6 +2094,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2254,6 +2449,11 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "jake": { "version": "10.8.5", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", @@ -2340,6 +2540,11 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, "minipass": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", @@ -2437,6 +2642,30 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + } + } + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -2541,6 +2770,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2725,6 +2959,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -2794,6 +3033,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -2849,6 +3093,11 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index fabc3e2..e03a73e 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "express-ip-block": "^0.1.2", "express-rate-limit": "^6.5.1", "express-session": "^1.17.2", - "mongoose": "^6.5.1" + "mongoose": "^6.5.1", + "multer": "^1.4.5-lts.1" } } diff --git a/public/images/avatars/default.jpg b/public/images/avatars/default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51d50f31d708dd0219ab1302fa12f908ba5e7b48 GIT binary patch literal 5453 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 literal 0 HcmV?d00001 diff --git a/routes/api/routes/users.js b/routes/api/routes/users.js index b82ff80..4342f63 100644 --- a/routes/api/routes/users.js +++ b/routes/api/routes/users.js @@ -1,6 +1,7 @@ const { UserModel, SecretModel } = require("../../../models"); const { Router } = require("express"); const { URLRegex } = require("../../../lib"); +const multer = require("multer"); const app = Router(); @@ -48,7 +49,6 @@ app.post("/:id/undelete/", async (req, res) => { }) - app.patch("/:id/", async (req, res) => { const { user, member } = req; @@ -79,5 +79,26 @@ app.patch("/:id/", async (req, res) => { res.complate(member); }) +const storage = multer.diskStorage({ + destination: function (_req, _file, cb) { + cb(null, './public/images/avatars') + }, + filename: function (req, _file, cb) { + cb(null, req.member.id + ".jpg") + } +}) + +const upload = multer({ storage }) + +app.put("/:id/", upload.single('avatar'), async (req, res) => { + const { member } = req; + + if (req.user.id !== member.id && !req.user.admin) return res.error(403, "You have not got permission for this."); + + if (!req.file) return res.error(400, "Missing avatar in request body."); + member.avatar = req.file.destination.slice("./public".length) + "/" + req.file.filename; + res.complate(await member.save()); +}); + module.exports = app; \ No newline at end of file diff --git a/routes/users.js b/routes/users.js index 3cfd1dc..dc6396b 100644 --- a/routes/users.js +++ b/routes/users.js @@ -1,6 +1,6 @@ const { Router } = require("express"); const app = Router(); -const {clearContent} = require("../lib"); +const { clearContent } = require("../lib"); const { UserModel, MessageModel, ThreadModel } = require("../models"); @@ -11,17 +11,15 @@ app.get("/", async (req, res) => { return res.reply("users", { users, page, pages: Math.ceil(await UserModel.count(query) / 10) }); }); -app.get("/:id/edit", async (req, res) => { +app.get("/:id/avatar", async (req, res) => { if (!req.user || (!req.user.admin && req.params.id !== req.user.id)) return res.error(403, "You have not got permission for this."); const member = await UserModel.get(req.params.id); if (member && (req.user?.admin || !member.deleted)) - res.reply("edit_user", { member }) + res.reply("avatar_upload", { member }) else res.error(404, `We don't have any user with id ${req.params.id}.`); - -}); - +}) app.get("/:id", async (req, res) => { const user = req.user const { id } = req.params; @@ -31,7 +29,7 @@ app.get("/:id", async (req, res) => { const message = await MessageModel.count({ authorID: id }); const thread = await ThreadModel.count({ authorID: id }); - member.about = clearContent( member.about) + member.about = clearContent(member.about) res.reply("user", { member, counts: { message, thread } }) } else res.error(404, `We don't have any user with id ${id}.`); diff --git a/views/avatar_upload.ejs b/views/avatar_upload.ejs new file mode 100644 index 0000000..2acfe0d --- /dev/null +++ b/views/avatar_upload.ejs @@ -0,0 +1,30 @@ + + + +<%- include("extra/meta", {title: "Avatar Upload Panel!" }) %> + + + <%- include("extra/navbar") %> +

Upload avatar for <%= member.name %>

+
+
+ +
+ + + + + \ No newline at end of file diff --git a/views/edit_user.ejs b/views/edit_user.ejs deleted file mode 100644 index 9ea25d8..0000000 --- a/views/edit_user.ejs +++ /dev/null @@ -1,53 +0,0 @@ - - - -<%- include("extra/meta", {title: "Edit "+member.name+"!" }) %> - - - - - - - <%- include("extra/navbar") %> - -

Edit <%= member.name %>

- -
-
- - - - <% if (user.admin){ %> - Is Admin? > - - <% } %> - - -
- -
- - - - - - - \ No newline at end of file diff --git a/views/messages.ejs b/views/messages.ejs index 338ad04..faf9a13 100644 --- a/views/messages.ejs +++ b/views/messages.ejs @@ -14,7 +14,7 @@
- +
<%= new Date(message.time).toLocaleDateString() %> diff --git a/views/thread.ejs b/views/thread.ejs index 80ef2d9..2c9d532 100644 --- a/views/thread.ejs +++ b/views/thread.ejs @@ -42,7 +42,7 @@
- +
<%= new Date(message.time).toLocaleDateString() %> diff --git a/views/user.ejs b/views/user.ejs index 1e75c73..9ed8f28 100644 --- a/views/user.ejs +++ b/views/user.ejs @@ -14,6 +14,7 @@
<% if (user?.admin || user?.id === member.id) { %> + Upload avatar Edit user!