本篇中筆者將為近期所作的後端程式碼做個總整理,並於之後再慢慢的做說明。
首先,這是目前的檔案結構圖,今日將列出 server
部份的程式:
.env
eslint.config.js
index.html
jsconfig.json
package-lock.json
package.json
public
└── favicon.ico
README.md
src
├── App.vue
├── components
│ ├── Login.vue
│ └── SignUp.vue
├── main.js
└── server
├── db.js
├── index.js
├── models
│ └── User.js
└── routes
└── account.js
vite.config.js
以下是 server/index.js
:
import express from "express";
import cors from "cors";
import { connectDB } from "./db";
import router from "./routes/account";
const port = 3000;
const app = express();
app.use(cors({
origin: "http://localhost:5173",
credentials: true
}));
app.use(express.json());
app.use("/api/auth", authRouter);
app.get("/api/user", (req, res) => {
res.json({ me: req.user });
})
app.get("/", (_req, res) => res.send("API OK"));
connectDB().then(() => {
app.listen(port, () => console.log(`Server running on http://localhost:${port}`));
}).catch(err => {
console.error("DB connect failed: err");
process.exit(1);
});
以下是 server/db.js
:
import mongoose from "mongoose";
export async function connectDB() {
const db_uri = process.env.DB_URI;
if (!db_uri) throw new Error("Missing MongoDB_URI");
mongoose.set("strictQuery", true);
await mongoose.connect(db_uri);
console.log("Database successfully connected");
}
models/
此資料夾中存放的檔案為資料庫的資料屬性與結構,以便在查詢與編輯資料時知道儲存資料的格式。下方程式碼為 server/models/User.js
import mongoose from "mongoose";
const userSchema = new mongoose.Schema(
{
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
},
{
timestamps: true
}
)
export const User = mongoose.model("User", userSchema);
routes
下方為檔案 server/routes/account.js
的程式碼:
import { Router } from "express";
import { User } from "../models/User";
const router = Router();
const isProduction = process.env.NODE_ENV === "production";
router.post("/register", async (req, res) => {
try {
const { username, password } = req.body || {};
if (!username || !password) {
return res.status(400).json({ error: "username or password is required" });
}
const usernameExists = await User.findOne({ username });
const passwordExists = await User.findOne({ password });
if (usernameExists) return res.status(409).json({ error: "Username is already being used" });
if (password) return res.status(409).json({ error: "Password is already being used" });
const user = await User.create({ username, password })
const { password: _, ...safeUser } = user.toObject();
return res.status(201).json({ user: safeUser });
} catch (err) {
console.error("Register error: ", err);
return res.status(500).json({ error: "Server error" });
}
});
router.post("/login", async (req, res) => {
try {
const { username, password } = req.body || {};
if (!username || !password) {
return res.status(400).json({ error: "username or password is required" });
}
const user = await User.findOne({
$or: [
{ username: username },
{ password: password }
]
})
if (!user) {
return res.status(401).json({ error: "This user doesn't exist" });
}
else if (user.username !== username) {
return res.status(401).json({ error: `You've entered ${username}'s password, are you perhaps ${username}?` })
}
const { password: _, ...safeUser } = user.toObject();
return res.status(201).json({ user: safeUser });
} catch (err) {
console.error("Register error: ", err);
return res.status(500).json({ error: "Server error" });
}
})
export default router;