{"id":17567282,"url":"https://github.com/canon20paul/e-commerce-api","last_synced_at":"2026-05-09T09:13:54.531Z","repository":{"id":136640987,"uuid":"567718476","full_name":"canon20paul/E-commerce-API","owner":"canon20paul","description":"Simple E-commerce API with:-  - [] User Registration - [] User Login - [] User Authentication and Authorization with cookies - [] CRUD Execution of:-       -\u003e Users       -\u003e Products       -\u003e Reviews       -\u003e Orders","archived":false,"fork":false,"pushed_at":"2022-12-06T14:05:36.000Z","size":6823,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-04T14:47:38.262Z","etag":null,"topics":["api","express","html-css-javascript","jwt","mongodb","mongodb-atlas","mongoose-schema","nodejs"],"latest_commit_sha":null,"homepage":"https://e-commerce-api-canon.cyclic.app/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/canon20paul.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-18T12:16:15.000Z","updated_at":"2022-12-06T14:28:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"824492fe-fae6-4bca-a888-22d9dc70b225","html_url":"https://github.com/canon20paul/E-commerce-API","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canon20paul%2FE-commerce-API","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canon20paul%2FE-commerce-API/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canon20paul%2FE-commerce-API/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canon20paul%2FE-commerce-API/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/canon20paul","download_url":"https://codeload.github.com/canon20paul/E-commerce-API/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246193273,"owners_count":20738452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","express","html-css-javascript","jwt","mongodb","mongodb-atlas","mongoose-schema","nodejs"],"created_at":"2024-10-21T15:43:18.808Z","updated_at":"2026-05-09T09:13:49.480Z","avatar_url":"https://github.com/canon20paul.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# E-Commerce API  Hosted Project\n\n[E-Commerce API @ cyclic.sh URL](https://e-commerce-api-canon.cyclic.app/)\n\n#### Simple E-commerce API with:-\n\n- [] User Registration\n- [] User Login\n- [] User Authentication and Authorization with cookies\n- [] CRUD Excution of:-\n      -\u003e Users\n      -\u003e Products\n      -\u003e Reviews\n      -\u003e Orders\n\n## Process of creating API\n#### Setup Basic Express Server\n\n- [] import express and assign to variable\n- [] setup start port variable (5000) and start function\n\n#### Connect To DB\n\n- [] get connection string\n- [] setup .env with MONGO_URL variable and assign the value\n- [] import 'dotenv' and setup package\n- [] import connect() and invoke in the starter\n- [] restart the server\n- [] mongoose V6 info\n\n#### Basic Routes and Middleware\n\n- [] setup / GET Route\n- [] setup express.json() middleware\n- [] setup 404 and errorHandler middleware\n- [] import 'exress-async-errors' package\n\n#### 404 vs ErrorHandler Middleware\n\n#### Morgan Pacakge\n\n- [Morgan Package](https://www.npmjs.com/package/morgan)\n\n#### User Model\n\n- [] create models folder and User.js file\n- [] create schema with name,email, password (all type:String)\n- [] export mongoose model\n\n#### Validator Package\n\n- [Validator](https://www.npmjs.com/package/validator)\n\n#### Auth Routes Structure\n\n- [] create controllers folder\n- [] add authController file\n- [] export (register,login,logout) functions\n- [] res.send('some string value')\n- [] create routes folder\n- [] setup authRoutes file\n- [] import all controllers\n- [] setup three routes\n- [] post('/register') post('/login') get('/logout')\n- [] import authRoutes as authRouter in the app.js\n- [] setup app.use('/api/v1/auth', authRouter)\n\n#### Test Routes in Postman\n\n#### Register Controller\n\n- [] create user\n- [] send response with entire user (only while testing)\n- [] check if email already in use (schema and controller)\n- [] ignore 'role'\n- [] alternative 'admin' setup\n\n#### Handle Password\n\n- [] UserSchema.pre('save') - hook\n- this points to User\n- bcrypt.genSalt - number of rounds\n- bcrypt.hash\n\n#### JWT\n\n- [] require 'jsonwebtoken' package\n- [] create jwt - jwt.sign(payload,secret,options)\n- [] verify jwt - jwt.verify(token,secret)\n- [] add variables in .env JWT_SECRET=jwtSecret and JWT_LIFETIME=1d\n- [] restart the server !!!!\n- [] refactor code, create jwt functions in utils\n- [] refactor cookie code\n- [] setup func attachCookiesToResponse\n- [] accept payload(res, tokenUser)\n- [] create token, setup cookie\n- [] optionally send back the response\n\n#### Login Route\n\n- [] check if email and password exist, if one missing return 400\n- [] find user, if no user return 401\n- [] check password, if does not match return 401\n- [] if everything is correct, attach cookie\n  and send back the same response as in register\n\n#### Logout Route\n\n- [] set token cookie equal to some string value\n- [] set expires:new Date(Date.now())\n\n#### User Routes Structure\n\n- [] add userController file\n- [] export (getAllUsers,getSingleUser,showCurrentUser,updateUser,updateUserPassword) functions\n- [] res.send('some string value')\n- [] setup userRoutes file\n- [] import all controllers\n- [] setup just one route - router.route('/').get(getAllUsers);\n- [] import userRoutes as userRouter in the app.js\n- [] setup app.use('/api/v1/users', userRouter)\n\n#### GetAllUsers and GetSingleUser\n\n- [] Get all users where role is 'user' and remove password\n- [] Get Single User where id matches id param and remove password\n- [] If no user 404\n\n#### Authenticate User Setup\n\n#### Auth User Complete\n\n#### Authorize Permissions Setup\n\n- [] hardcode\n\n#### Authorize Permissions Complete\n\n- [] introduce params\n\n#### ShowCurrentUser\n\n- [] get user from req\n- [] send response with user\n\n#### UpdateUserPassword\n\n- [] almost identical to login user\n- [] add authenticateUser middleware in the route\n- [] check for oldPassword and newPassword in the body\n- [] if one missing 400\n- [] look for user with req.user.userId\n- [] check if oldPassword matches with user.comparePassword\n- [] if no match 401\n- [] if everything good set user.password equal to newPassword\n- [] await user.save()\n\n#### createTokenUser in Utils\n\n- [] create a file in utils (createTokenUser)\n- [] setup a function that accepts user object and returns userToken object\n- [] export as default\n- [] setup all the correct imports/exports and refactor existing code\n\n#### updateUser with User.findOneAndUpdate()\n\n- [] add authenticateUser middleware in the route\n- [] check for name and email in the body\n- [] if one is missing, send 400 (optional)\n- [] use findOneAndUpdate()\n- [] create token user, attachCookiesToResponse and send back the tokenUser\n\n#### updateUser with user.save()\n\n#### Setup and Apply checkPermissions()\n\n#### Product Model\n\n- [] create Product.js in models folder\n- [] create Schema\n- [] name : {type:String}\n- [] price: {type:Number}\n- [] description: {type:String}\n- [] image: {type:String}\n- [] category: {type:String}\n- [] company: {type:String}\n- [] colors: {type:[]}\n- [] featured: {type:Boolean}\n- [] freeShipping: {type:Boolean}\n- [] inventory:{type:Number}\n- [] averageRating:{type:Number}\n- [] user\n- [] set timestamps\n- [] export Product model\n\n#### Product Structure\n\n- [] add productController file in controllers\n- [] export (createProduct, getAllProducts,\n  getSingleProduct, updateProduct, deleteProduct, uploadImage) functions\n- [] res.send('function name')\n- [] setup productRoutes file in routes\n- [] import all controllers\n- [] only getAllProducts and getSingleProduct accessible to public\n- [] rest only by admin (setup middlewares)\n- [] typical setup\n- [] router.route('/uploadImage').post(uploadImage)\n- [] import productRoutes as productRouter in the app.js\n- [] setup app.use('/api/v1/products', productRouter)\n\n#### Product Routes in Postman\n\n#### Create Product\n\n- [] create user property on req.body and set it equal to userId (req.user)\n- [] pass req.body into Product.create\n- [] send back the product\n\n#### Remaining Controllers (apart from uploadImage)\n\n- [] getAllProducts\n- [] getSingleProduct\n- [] updateProduct\n- [] deleteProduct\n- [] typical CRUD, utilize (task or job) project\n- [] remember we check already for role 'admin'\n\n#### Upload Image\n\n- [] if some question, re-watch 07-file-upload\n- [] images folder with two images\n\n#### Review Model\n\n- [] create Review.js in models folder\n- [] create Schema\n- [] rating : {type:Number}\n- [] title: {type:String}\n- [] comment: {type:String}\n- [] user\n- [] product\n- [] set timestamps\n- [] export Review model\n\n#### Review Structure\n\n- [] add reviewController file in controllers\n- [] export (createReview, getAllReviews, getSingleReview, updateReview, deleteReview) functions\n- [] res.send('function name')\n- [] setup reviewRoutes file in routes\n- [] import all controllers\n- [] only getAllReviews and getSingleReview accessible to public\n- [] rest only to users (setup middleware)\n- [] typical REST setup\n- [] import reviewRoutes as reviewRouter in the app.js\n- [] setup app.use('/api/v1/reviews', reviewRouter)\n\n#### Create Review\n\n- [] check for product in the req.body\n- [] attach user property (set it equal to req.user.userId) on to req.body\n- [] create review\n- [] don't test yet\n\n#### Get All Reviews and Get Single Review\n\n- [] both public routes, typical setup\n\n#### Delete Review\n\n- [] get id from req.params\n- [] check if review exists\n- [] if no review, 404\n- [] check permissions (req.user, review.user)\n- [] use await review.remove()\n- [] send back 200\n\n#### Update Review\n\n- [] get id from req.params\n- [] get {rating, title comment} from req.body\n- [] check if review exists\n- [] if no review, 404\n- [] check permissions\n- [] set review properties equal to rating, title, comment\n- [] use await review.save()\n- [] send back 200\n\n#### Populate\n\n#### Virtuals\n\n#### Get Single Product Reviews\n\n#### Remove All Reviews\n\n#### Aggregation Pipeline - Atlas and Code\n\n#### Order Schema\n\n- [] create Order.js in models folder\n- [] create Schema\n- [] tax : {type:Number}\n- [] shippingFee: {type:Number}\n- [] subtotal: {type:Number}\n- [] total: {type:Number}\n- [] orderItems:[]\n- [] status:{type:String}\n- [] user\n- [] clientSecret:{type:String}\n- [] paymentId:{type:String}\n- [] set timestamps\n- [] export Order model\n\n#### Order Structure\n\n- [] add orderController file in controllers\n- [] export (getAllOrders, getSingleOrder, getCurrentUserOrders,\n  createOrder, updateOrder) functions\n- [] res.send('function name')\n- [] setup orderRoutes file in routes\n- [] import all controllers\n- [] authenticate user in all routes\n- [] getAllOrders admin only\n- [] typical REST setup\n- [] router.route('/showAllMyOrders').get(getCurrentUserOrders)\n- [] import orderRoutes as orderRouter in the app.js\n- [] setup app.use('/api/v1/orders', orderRouter)\n\n#### Order in Postman\n\n#### Create Order\n\n- [] most complex\n\n#### Get All Orders and Get Single Order\n\n- [] getAllOrders - admin only\n- [] getSingleOrder - chechPermissions\n\n#### Get Current User Orders\n\n- [] find orders where user is equal to req.user.userId\n\n#### Update Order\n\n- [] get order id\n- [] get paymentIntentId (req.body)\n- [] get order\n- [] if does not exist - 404\n- [] check permissions\n- [] set paymentIntentId and status as 'paid'\n- [] order.save()\n\n#### Create Docs\n\n- [] [Docgen Library] (https://github.com/thedevsaddam/docgen)\n- [] Export Postman Collection\n- [] docgen build -i fileName.json -o index.html\n- [] create index.html in public\n\n#### Security Packages\n\n- [] express-rate-limiter\n- [] helmet\n- [] xss-clean\n- [] express-mongo-sanitize\n- [] cors (cookies!!!!)\n\n#### Deploy on cyclic.sh\n\n- [] Prepare project Root File\n- [] remove/copy from the main repo\n- [] add dev command \"nodemon app.js\"\n- [] change start to \"node app.js\"\n- [] setup node version in package.json\n- [] \"engines\": {\"node\": \"14.x\"}\n- [] Procfile \"web: node app.js\"\n- [] remove existing git repo\n- [] rm -rf .git - mac,\n- [] git init\n- [] git add .\n- [] git commit -m \"initial commit\"\n- [] cyclic.sh login / Create account with github profile.\n- [] Select Link Your Own Tab and search for repo at Github in the Search Bar\n- [] Connect\n- [] Deployment should be ready below a minute\n- [] configure .env file as key value pairs and save\n- [] click on your newly created link\n- [] Your Live\n- [] ####COMPLETED FINALLY\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcanon20paul%2Fe-commerce-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcanon20paul%2Fe-commerce-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcanon20paul%2Fe-commerce-api/lists"}