-
Notifications
You must be signed in to change notification settings - Fork 0
basic express app created #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import mongoose from "mongoose"; | ||
|
|
||
| const connectDB = async () => { | ||
| try { | ||
| console.log("Connecting to MongoDB..."); | ||
| await mongoose.connect(process.env.MONGODB_URI!); | ||
| console.log("✅ MongoDB Connected"); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| export default connectDB; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| import { Request, Response } from "express"; | ||
| import jwt from 'jsonwebtoken' | ||
| import { User } from "../models/User.js"; | ||
| import bcrypt from "bcrypt"; | ||
| import { AuthRequest } from "../middlewares/auth.js" | ||
|
|
||
| // Helper to generate JWT Token | ||
| const generateToken = (id: string)=>{ | ||
| return jwt.sign({id}, process.env.JWT_SECRET as string, {expiresIn: "30d"} ) | ||
|
Comment on lines
+8
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n -C3 'JWT_SECRET|dotenv|config\(' server --glob '*.ts'Repository: prepwave/QuickDine Length of output: 1221 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n== server/controllers/authControllers.ts ==\n'
cat -n server/controllers/authControllers.ts | sed -n '1,220p'
printf '\n== server/server.ts ==\n'
cat -n server/server.ts | sed -n '1,120p'
printf '\n== server/middlewares/auth.ts ==\n'
cat -n server/middlewares/auth.ts | sed -n '1,160p'Repository: prepwave/QuickDine Length of output: 8305 Validate 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| // Resister a new User | ||
| // Post /api/uath/register | ||
| export const registerUser = async (req: Request, res: Response): Promise<void> => { | ||
| try{ | ||
| const { name, email, password, phone, role } = req.body; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win Do not let public registration assign privileged roles. A caller can submit Proposed fix- const { name, email, password, phone, role } = req.body;
+ const { name, email, password, phone } = req.body;
...
- role,Also applies to: 33-39 🤖 Prompt for AI Agents |
||
|
|
||
| if(!name || !email || !password){ | ||
| res.status(400).json({message: "Please Enter all required Fieds"}) | ||
| return; | ||
| } | ||
| // Check if user exists | ||
| const userExists = await User.findOne({email}) | ||
| if(userExists){ res.status(400).json({message: "User already exists "}) | ||
| return; | ||
| } | ||
|
|
||
| // Hash password | ||
| const salt = await bcrypt.genSalt(10) | ||
| const hashedPassword = await bcrypt.hash(password, salt) | ||
|
|
||
| // creat user | ||
| const user = await User.create({ | ||
| name, | ||
| email, | ||
| password: hashedPassword, | ||
| phone, | ||
| role, | ||
| }) | ||
|
|
||
| if(user){ | ||
| res.status(201).json({ | ||
| _id: user._id, | ||
| name: user.name, | ||
| email: user.email, | ||
| phone: user.phone, | ||
| role: user.role, | ||
| token: generateToken(user._id.toString()) | ||
| }) | ||
| }else{ | ||
| res.status(400).json({message: "Invailid User data"}); | ||
| } | ||
| } catch (error : any){ | ||
| console.error(error); | ||
| res.status(400).json({message: error.message}); | ||
|
Comment on lines
+53
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Do not return raw internal errors to clients. These catch-all blocks expose database/JWT implementation details via Also applies to: 94-96 🤖 Prompt for AI Agents |
||
|
|
||
| } | ||
| } | ||
|
|
||
| // Authentication a User & get token | ||
| // Post /api/uath/register | ||
| export const loginUser = async (req: Request, res: Response): Promise<void> => { | ||
| try{ | ||
| const { email, password} = req.body; | ||
|
|
||
| if( !email || !password){ | ||
| res.status(400).json({message: "Please provide email and password"}) | ||
| return; | ||
| } | ||
| // Check for user | ||
| const user = await User.findOne({email}) | ||
| if(!user){ | ||
| res.status(400).json({message: "Invailid email or password"}); | ||
| return; | ||
|
|
||
| } | ||
|
|
||
| // Check if password matches (useeer.password isnot undefined because we queried it ) | ||
| const isMatch = await bcrypt.compare(password, user.password || "" ) | ||
| if(!isMatch){ | ||
| res.status(400).json({message: "Invailid email or password"}); | ||
| return; | ||
| } | ||
| res.json({ | ||
| _id: user._id, | ||
| name: user.name, | ||
| email: user.email, | ||
| phone: user.phone, | ||
| role: user.role, | ||
| token: generateToken(user._id.toString()) | ||
| }) | ||
|
|
||
|
|
||
| } catch (error: any){ | ||
| console.error(error); | ||
| res.status(400).json({message: error.message}); | ||
|
|
||
| } | ||
| } | ||
| // get user profile | ||
| // GET /api/uath/me | ||
| // access Private | ||
| export const getMe = async (req: AuthRequest, res: Response): Promise<void> => { | ||
| try{ | ||
| if (!req.user){ | ||
| res.status(401).json({message: "Not Authorized"}) | ||
| return; | ||
|
|
||
| } | ||
| res.json(req.user) | ||
| } catch (error) { | ||
| console.error(error); | ||
|
|
||
| if (error instanceof Error) { | ||
| res.status(400).json({ | ||
| message: error.message | ||
| }); | ||
| } else { | ||
| res.status(400).json({ | ||
| message: "Unknown error" | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| import { Request, Response, NextFunction } from "express"; | ||
| import jwt from "jsonwebtoken"; | ||
| import { User, IUser } from "../models/User.js"; | ||
|
|
||
| export interface AuthRequest extends Request { | ||
| user?: IUser; | ||
| } | ||
|
|
||
| export const protect = async ( | ||
| req: AuthRequest, | ||
| res: Response, | ||
| next: NextFunction | ||
| ): Promise<void> => { | ||
|
|
||
| let token; | ||
|
|
||
| if ( | ||
| req.headers.authorization && | ||
| req.headers.authorization.startsWith("Bearer") | ||
| ) { | ||
| try { | ||
|
|
||
| token = req.headers.authorization.split(" ")[1]; | ||
|
|
||
| const decoded = jwt.verify( | ||
| token, | ||
| process.env.JWT_SECRET! | ||
| ) as { id: string }; | ||
|
|
||
| const user = await User.findById(decoded.id).select("-password"); | ||
|
|
||
| if (!user) { | ||
| res.status(401).json({ | ||
| message: "Not authorized, user not found" | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| req.user = user; | ||
|
|
||
| next(); | ||
|
|
||
| } catch (error) { | ||
| console.error("Auth Middleware Error:", error); | ||
|
|
||
| res.status(401).json({ | ||
| message: "Not authorized, token failed" | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| if (!token) { | ||
| res.status(401).json({ | ||
| message: "Not authorized, no token" | ||
| }); | ||
| return; | ||
| } | ||
| } | ||
| export const adminOnly = (req: AuthRequest, res: Response, next: NextFunction ): void=> { | ||
| if(req.user &&req.user.role==="admin"){ | ||
| next() | ||
| }else{ | ||
| res.status(403).json({message:" Access denied, admin role required"}); | ||
| } | ||
| } | ||
|
|
||
| export const ownerOnly = (req: AuthRequest, res: Response, next: NextFunction ): void=> { | ||
| if(req.user &&(req.user.role==="owner"|| req.user.role==="admin")){ | ||
| next() | ||
| }else{ | ||
| res.status(403).json({message:" Access denied, admin role required"}); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import {Document, model, Schema } from "mongoose" | ||
|
|
||
| export interface IUser extends Document{ | ||
| name: string; | ||
| email: string; | ||
| password?: string; | ||
| phone?: string; | ||
| role: "user" | "admin" | "owner"; | ||
| createdAt: Date; | ||
| updatedAt: Date; | ||
| } | ||
|
|
||
| const UserSchema = new Schema<IUser>( | ||
| { | ||
| name: {type: String, required: true, trim: true}, | ||
| email: {type: String, required: true, unique: true, trim: true, lowercase: true}, | ||
| password: {type: String, required: true, minlength: 6}, | ||
| phone: {type: String, trim: true, minlength: 6 }, | ||
| role: {type: String, enum: ["user" , "admin" , "owner"], default: "user"}, | ||
|
|
||
| }, | ||
| {timestamps: true} | ||
|
|
||
|
|
||
| ) | ||
| // Remove password when converting to JSON | ||
| UserSchema.set("toJSON", { | ||
| transform: (doc, ret)=>{ | ||
| delete ret.password; | ||
| return ret; | ||
| } | ||
| }) | ||
| export const User = model<IUser>("User", UserSchema) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
Connection failures are swallowed — server will start without a DB.
catchonly logs; it never exits or rethrows, soawait connectDB()inserver.tsalways resolves and the HTTP listener starts regardless of connection outcome. Combined with the non-null assertion onMONGODB_URI(no validation that it's actually set), a misconfigured environment fails silently and the app serves traffic that will error on every DB-touching request instead of failing fast at startup.🐛 Suggested fix
import mongoose from "mongoose"; const connectDB = async () => { + const uri = process.env.MONGODB_URI; + if (!uri) { + throw new Error("MONGODB_URI is not defined"); + } try { console.log("Connecting to MongoDB..."); - await mongoose.connect(process.env.MONGODB_URI!); + await mongoose.connect(uri); console.log("✅ MongoDB Connected"); } catch (error) { console.error(error); + process.exit(1); } }; export default connectDB;📝 Committable suggestion
🤖 Prompt for AI Agents