Ich entwickle eine sehr einfache Social-Media-Anwendung, bei der Benutzer sich registrieren, anmelden, Beiträge erstellen, ihr Profil und ihre Beiträge bearbeiten, Beiträge löschen und sich selbst vollständig löschen können.
Tokens über JWT sollten ordnungsgemäß erstellt und verwendet werden und Benutzer sollten alle relevanten Dateien in Cloudinary hochladen. Dabei werden Profilbilder im Ordner „profile_pictures“ und Beiträge im Ordner „user_posts“ gespeichert.
Das alles hat beim Test letzten Freitag funktioniert. Als ich mich nun jedoch hinsetze, um die Tokens im Frontend zu reparieren, kann ich plötzlich keine Benutzer mehr registrieren. Also ging ich zum Backend, überprüfte den Code, ging zu Postman, testete das Routing und es füllte den Anfragetext nicht aus.
Mehr Probleme jetzt, zum Beispiel funktioniert das Hochladen von Dateien in Cloudinary auch nicht mehr. Ich weiß nicht, ob das am jüngsten API-Update liegt, obwohl auf der Seite „letzte Aktualisierung“ am 15. Juni steht, meine letzte Registrierung und Anmeldung Der Test fand am Freitag, dem 16. Juni, statt, was mich zu dem Schluss brachte, dass es auch jetzt noch funktionieren sollte
All das ist jedoch nicht der Grund, warum ich diese Frage stelle und um Hilfe bitte. Ich habe den gesamten Datei-Upload-bezogenen Code in der Anwendung deaktiviert, um die Erstellung von Mongo DB Atlas-Benutzerobjekten zu testen.Hier liegt mein Problem. Aus irgendeinem Grund, der außerhalb meines Wissens und Verständnisses liegt, füllt Postman nichts mit den Formulardaten, obwohl alles in Ordnung zu sein scheint, der Inhaltstyp korrekt ist und die Felder des erstellten Benutzerobjekts korrekt sind.
Wenn ich Roheingaben in Postman verwende, werden diese einfach ausgefüllt. Ich bin mit meiner Weisheit am Ende...
Wenn jemand dieses Problem kennt, würde ich mich sehr über Ihre Hilfe freuen.
Das Folgende ist der relevante Code. Bitte ignorieren Sie die auskommentierten dateibezogenen Codezeilen.
// AUTH CONTROLLER: // controller for user signup module.exports.signup = async (req, res, next) => { try { console.log(req.body, "req body"); // retrieve user from db by email provided in request body const foundUser = await User.findOne({ email: req.body.email }); console.log(foundUser, "found user"); // check if foundUser already exists in db if (foundUser) { res.status(409).json({ message: `Email already in use. Please choose another.` }); } // generate salt and hash for the user password const salt = bcrypt.genSaltSync(Number(process.env.SALT_ROUND)); const hash = bcrypt.hashSync(req.body.password, salt); // create a new user object from user model const newUser = new User({ username: req.body.username, name: req.body.name, email: req.body.email, password: hash, //profilePicture: req.file.path }); // console.log(req.file, "req file"); await newUser.save(); // save the new user object to the database // upload the profile picture to cloudinary storage // const result = await cloudinary.uploader.upload(req.file.path, { // public_id: `profile_pictures/${newUser._id}`, // }); //newUser.profilePicture = result.secure_url; //await newUser.save(); // update newUser with the profilePicture URL console.log(newUser, "new user"); // generate a signup token // const token = jwt.sign({ newUserId: newUser._id, newUserName: newUser.username, newUserProfilePicture: newUser.profilePicture }, process.env.JWT_SECRET, { // expiresIn: '5m' // expires in 5 minutes (in case signup was erroneous) // }); // store the token as a cookie // res.cookie('jwt', token, { // httpOnly: true // }); // respond with the newly created user object and the created token res.status(201).json({ message: `User created successfully!`, user: newUser }); } catch (err) { next(err); }; };
// AUTH ROUTE: // import dependencies const express = require('express') const authController = require('../controllers/authController') //const authHandler = require('../middlewares/authHandler') // create new router object const router = express.Router() // import controllers router.post('/signup', authController.signup) //router.post('/login', authController.login) //router.get('/logout', authHandler.checkUser, authController.logout) module.exports = router
// USER MODEL: const mongoose = require("mongoose") const bcrypt = require("bcrypt") const UserSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, password: { type: String, required: true }, name: { type: String, required: true }, username: { type: String, unique: true }, //profilePicture: { type: String }, }) // usually you hash/salt inside the appropriate model; like our userModel here. // // but we save the user-object twice for following two reasons: // - the regular data of the user-object gets saved to our mongoDB atlas database. // - and the profile picture gets uploaded and saved in an appropriate folder to cloudinary. // // this triggers the password hash twice, which in return falsifies the user password on login attempt. // therefore we ignore the code snippet below and directly salt and hash in our authController. // // hash and salt user password before saving to database // UserSchema.pre("save", async function (next) { // const salt = await bcrypt.genSalt(); // this.password = await bcrypt.hash(this.password, salt); // next(); // }); // pre-hook for updating password field UserSchema.pre('findOneAndUpdate', function (next) { const update = this.getUpdate() if (update.password) { bcrypt.hash(update.password, Number(process.env.SALT_ROUND), function (err, hash) { if (err) return next(err) update.password = hash next() }) } }) // compare the password entered by the user with the hashed password in the database UserSchema.methods.comparePassword = function (candidatePassword, cb) { bcrypt.compare(candidatePassword, this.password, function (err, isMatch) { if (err) return cb(err) //cb(err) passes errors down to error handler the same way next(err) does cb(null, isMatch) }) } const User = mongoose.model("User", UserSchema) module.exports = User
// SERVER: // import dependencies const cors = require('cors'); const express = require('express'); const cookieParser = require('cookie-parser'); // import routes (modules) const authRoute = require('./routes/authRoute'); const userRoute = require('./routes/userRoute'); const postRoute = require('./routes/postRoute'); const app = express(); // initialize express // import middlewares const { connectMongoDB } = require('./lib/mongoose'); // destruct mongoDB connector const { errorHandler } = require('./middlewares/errorHandler'); // destruct errorHandler // allow requests from specified origins with specific methods const whitelist = [process.env.FRONTEND_URL, 'https://www.arii.me']; // add cors options const corsOptions = { origin: (origin, callback) => { if (whitelist.indexOf(origin) !== -1 || !origin) { callback(null, true); } else { callback(new Error('CORS issues')); }; }, credentials: true, }; // enable cross-origin resource sharing with specified options for the express app app.use(cors(corsOptions)); // parse incoming cookies and make them accessible in req.cookies app.use(cookieParser()); // enable parsing of incoming JSON data in the request body by the express app app.use(express.json()); app.use(express.urlencoded({ extended: false })); // define routes app.use('/auth', authRoute); app.use('/users', userRoute); app.use('/posts', postRoute); // define middlewares connectMongoDB(); app.use(errorHandler); // error handler must be last invoked middleware // listen to server app.listen(process.env.PORT || 3003, () => { console.log(`Server up and running at ${process.env.PORT}`); });
// MONGOOSE: // import dependencies const mongoose = require('mongoose'); require('dotenv').config(); // destruct envs const { DB_USER, DB_PASS, DB_HOST, DB_NAME } = process.env; // atlas connection string const mongoURI = `mongodb+srv://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_NAME}?retryWrites=true&w=majority`; // middleware function for handling connections to the mongoDB atlas database module.exports.connectMongoDB = async () =>{ try { await mongoose.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true, }); console.log(`Connected to MongoDB Atlas!`); } catch (err) { console.log(`Couldn't Connect to MongoDB Atlas!`); next(err); } }Entschuldigung, wenn das zu viel ist, aber das ist der gesamte relevante Code und ich habe den Verstand verloren. Ich weiß, dass es nicht ratsam ist, ENV offenzulegen, aber das ist nur eine Übung für mich selbst, daher habe ich keine Bedenken, ENV weiterzugeben.
Ich schätze wirklich jede Meinung zu diesem Thema.
Update:
Ich habe das Problem behoben, bei dem der Anfragetext nicht mit dem folgenden Code gefüllt war:
// In the auth route I imported multer: const multer = require('multer') const upload = multer() // Then I added a method to the auth route before signup is called: router.post('/signup', upload.none(), authController.signup) // I have also forfeited any file upload during signup // and replaced them with a default image in my cloudinary assets. // Here's the updated userModel profilePicture field: profilePicture: { type: String, default: 'res.cloudinary.com/ddb2abwuu/image/upload/v1687256495/…' }Wenn Sie diese Schritte befolgen, wird der Anfragetext nun korrekt ausgefüllt und ich kann auch Postman-Formulardaten verwenden und den Benutzer erneut im Frontend erstellen.
Benutzer können das Standardprofilbild später ändern, indem sie ihr eigenes Profil über den Patcher hochladen. Andere Websites handhaben die Nutzerakquise auf ähnliche Weise.
Fragen Sie mich nicht, warum ich plötzlich diese mentale Gymnastik machen muss, obwohl alles genauso gut funktioniert wie vor ein paar Tagen, hier sind wir.
Ich vermute stark, dass es bei mindestens einem der Pakete und Abhängigkeiten, die ich verwende, eine Art API-Update gab, das mich völlig durcheinander gebracht hat.
Zum jetzigen Zeitpunkt wurde dieses Problem gelöst. Ich hoffe, dass dies für jeden nützlich ist, der in Zukunft auf das gleiche seltsame Problem stößt.
到目前为止,我找到了一个令我难以置信的解决方案:在我的 authRoute 中,我必须显式导入 multer 然后创建
然后在身份验证路由中指定:
我还放弃了注册过程中的任何文件上传,只是手动将默认的个人资料图片添加到我的 cloudinary 资产中,并将其添加到我的用户模型中:
这样注册和登录就可以再次工作了。
通过执行这些步骤,它现在可以正确填充请求正文,我也可以使用 Postman 表单数据和在前端再次创建用户。
用户可以选择稍后通过修补程序上传自己的配置文件来更改默认的配置文件图片。其他网站以类似的方式处理用户获取。
不要问我为什么我必须突然做这些心理体操,虽然一切都像几天前一样有效,但我们已经到了。
我强烈怀疑我使用的至少一个包和依赖项有某种 API 更新,这完全把我搞砸了。
就目前情况而言,此问题现已解决。希望这对将来遇到同样奇怪问题的人有用。