Git Product home page Git Product logo

eshop-backend-base's Introduction

eshop-backend-base

This is a simple E-shop backend created with the following technologies:

NOTE: This application was created within a week and is not production-ready. It probably has a ton of bugs.

Set up

Remember to do every step described below to fully set up the application.

Repository

git clone https://github.com/jonisavo/eshop-backend-base.git
cd eshop-backend-base
npm install

.env file

The app fetches various information from a .env file, which should be located in the root folder. You must create it yourself. It looks like this:

API_URL = /api/v1
PORT = 3000
MONGO_CONSTRING = mongodb+srv://...

Where API_URL is the base url of your API (e.g. http://localhost:3000/api/v1) and MONGO_CONSTRING is the credentials used to connect to your MongoDB database. PORT is the the port used by the server.

The .env file is ignored by Git. Remove it from the .gitignore file to be able to check it into version control, but remember to not publish it!

MongoDB

Enter your database connection string to the .env file as described above. Also, in the MongoDB web client, you must allow your IP address to access the database via the Network > Network Access menu.

JSON Web Tokens

The JSON web tokens are generated using a secret, which is read from a file named jwtRS256.key. You must create it yourself. It may look something like this:

-----BEGIN RSA PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...

Refer to https://gist.github.com/ygotthilf/baa58da5c3dd1f69fae9 on how to generate a key.

The jwtRS256.key file is also ignored by Git. Be careful with exposing it to version control.

Usage

npm start

If you see

The server is running in port 3000
Database connection is ready...

you are good to go!

Schemas

Category

{
  name: {
    type: String,
    required: true,
  },
  color: {
    type: String,
    default: '',
  },
  icon: {
    type: String,
    default: '',
  },
  image: {
    type: String,
    default: '',
  },
}

Product

{
  name: {
    type: String,
    required: true,
  },
  description: {
    type: String,
    required: true,
  },
  richDescription: {
    type: String,
    default: '',
  },
  image: {
    type: String,
    default: '',
  },
  images: [{
    type: String,
  }],
  brand: {
    type: String,
    default: '',
  },
  price: {
    type: Number,
    required: true,
    min: 0,
  },
  category: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
    required: true,
  },
  stock: {
    type: Number,
    required: true,
    min: 0,
  },
  rating: {
    type: Number,
    default: 0.0,
    min: 0.0,
    max: 5.0,
  },
  numReviews: {
    type: Number,
    default: 0,
    min: 0,
  },
  isFeatured: {
    type: Boolean,
    default: false,
  },
  dateCreated: {
    type: Date,
    default: Date.now,
  },
}

User

{
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  passwordHash: {
    type: String,
    required: true
  },
  phone: {
    type: String,
    default: ''
  },
  isAdmin: {
    type: Boolean,
    default: false
  },
  street: {
    type: String,
    default: ''
  },
  apartment: {
    type: String,
    default: ''
  },
  zip: {
    type: String,
    default: ''
  },
  city: {
    type: String,
    default: ''
  },
  country: {
    type: String,
    default: ''
  },
  dateRegistered: {
    type: Date,
    default: Date.now,
  },
}

Order

{
  orderItems: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'OrderItem',
    required: true
  }],
  shippingAddress1: {
    type: String,
    required: true
  },
  shippingAddress2: {
    type: String,
    default: ''
  },
  city: {
    type: String,
    required: true
  },
  country: {
    type: String,
    required: true
  },
  phone: {
    type: String,
    default: ''
  },
  status: {
    type: String,
    required: true,
    default: OrderStatus.PENDING
  },
  totalPrice: {
    type: Number,
    min: 0,
    default: 0
  },
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    required: true
  },
  dateOrdered: {
    type: Date,
    default: Date.now
  }
}

Order item

{
  quantity: {
    type: Number,
    required: true,
    min: 0,
    max: 99
  },
  product: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Product',
    required: true
  }
}

API

In a nutshell

  • API_URL/categories
    • GET /: get all categories
    • GET /:id: get a single category
    • POST /: create a new category
    • PUT /:id: update an existing category
    • DELETE /:id: remove an existing category
  • API_URL/products
    • GET /: get all products
      • GET /?categories=x,y: filter by given categories
    • GET /brief: get all products with only the name and image returned
      • GET /brief?categories=x,y
    • GET /:id: get a single product
    • GET /brief/:id
    • GET /get/count: get the count of products
    • GET /get/featured: get all featured products
      • GET /get/featured/:count: get first :count featured products
    • POST /: create a new product
    • PUT /:id: update an existing product
    • PUT /:id/gallery: upload additional images for the product
    • DELETE /:id: remove an existing product
  • API_URL/users
    • GET /: get all users
    • GET /:id: get a single user
    • GET /get/count: get the user count
    • POST /: create a new user
    • POST /register: create a new user
    • POST /login: log in with an email and password
    • POST /change/password: change the password of a user
    • PUT /:id: update an existing user
    • DELETE /:id: remove an existing user
  • API_URL/orders
    • GET /: get all orders
    • GET /:id: get a single order
    • GET /get/user/:id: get all orders for the given user
    • GET /get/count: get total order count
    • GET /get/totalsales: get total sales
    • POST /: create a new order
    • POST /:id/set/status/:status: set order :order status to :status
    • PUT /:id: update an existing order
    • DELETE /:id: remove an existing order

General

All responses are either in the form of

{
    "success": true,
    "result": {} // can also be an array of objects or a primitive value, see in-depth documentation below
}

or

{
    "success": false,
    "error": {
        "_toString": "message",
        "_code": 900
        // can also contain other data included in the error
    }
}

For all possible error codes for the _code field, see error_codes.js.

The API is secured with JSON web tokens, which contain the user ID and admin flag. The admin flag is used to determine whether the user should have access to certain functions.

/categories

GET /

Returns all categories.

GET /:id

Returns a single category with id :id. Returns a 404 error if none exists.

POST /

Requires admin status.

Creates a new category with the provided information.

PUT /:id

Requires admin status.

Updates an existing category, changing only the values given. Returns a 404 error if the category does not exist.

DELETE /:id

Requires admin status.

Removes a category with id :id. Returns a 404 error if the category does not exist.

/products

GET /

Returns a list of all products. The list can be filtered by category with the ?categories=x,y query parameter.

Example:

GET https://localhost:3000/api/v1/products?categories=6027dce9b0aea13ac46c4299,61274f9bb8aec707ec60ef4d

GET /brief

Returns a list of all products, returning only their name and image fields. The list can be filtered with ?categories=x,y.

GET /:id

Returns a single product, or a 404 error if none exists.

GET /brief/:id

Returns a single product's name and image fields, or a 404 error if the product does not exist.

GET /get/count

Returns the product count. A successful response looks like

{
  "success": true,
  "result": 5
}

GET /get/featured

Returns all featured products.

GET /get/featured/:count

Returns the :count first featured products.

POST /

Requires admin status.

Creates a new product with the provided information. Validates the product's category. An image must be uploaded with the image key.

PUT /:id

Requires admin status.

Updates an existing product, changing only the values given. Returns a 404 error if the product does not exist. The image can be changed with the image key.

PUT /:id/gallery

Requires admin status.

Uploads additional images to the product, with to 20 at a time. The images are sent with the images key.

DELETE /:id

Requires admin status.

Removes a product with id :id. Returns a 404 error if the category does not exist.

/users

GET /

Requires admin status.

Returns a list of all users. The hashed password is omitted.

GET /:id

Requires authorization.

Returns a single user with id :id, or a 404 error if none exists. The hashed password is omitted.

The user must be logged in as the user whose information is being accessed. Admins can fetch the information of any user.

GET /get/count

Requires admin status.

Returns the total user count.

POST /

Requires admin status.

Creates a new user with the provided information. A plaintext password is given in the password field, which is then hashed in the backend and stored as the passwordHash property. Only one user can be created for each e-mail.

POST /register

A user-facing alias for POST /.

POST /login

Log in to the server. Takes an email and plaintext password in the form of

{
  "email": "[email protected]",
  "password": "password"
}

and replies with a JWT token if authentication was successful:

{
  "success": true,
  "result": {
    "user": "[email protected]",
    "id": "...",
    "token": "..."
  }
}

An error will be returned if the user is already logged in.

POST /change/password

Change the password of a user. Takes an email, the current password and new password:

{
  "email": "[email protected]",
  "currentPassword": "password",
  "newPassword": "password2"
}

Fails if:

  • User with given e-mail does not exist
  • Current password is wrong
  • New password is the same as the current password

PUT /:id

Requires admin status.

Updates an existing user, changing only the values given. Returns a 404 error if the user does not exist.

DELETE /:id

Requires admin status.

Removes a user with id :id. Returns a 404 error if the user does not exist.

/orders

GET /

Requires admin status.

Returns a list of all orders.

GET /:id

Requires authorization.

Returns a single order with id :id, or a 404 error if none exists.

An order can be fetched if it has been made by the authorized user. Attempting to fetch an order made by someone else will result in a 404 error. Admins can fetch any order.

GET /get/user/:id

Requires authorization.

Returns all orders made by a user with id :id. If the user is authorized, they can view their own orders. Admins can view anyone's orders.

GET /get/count

Requires admin status.

Returns the total count of orders.

GET /get/totalsales

Requires admin status.

Returns the total sum of all sales.

POST /

Requires admin status.

Creates a new order with the provided information.

POST /:id/set/status/:status

Requires admin status.

Changes the order :id's status to :status, which can be one of the following:

  • pending
  • shipped
  • cancelled

PUT /:id

Requires admin status.

Updates an existing order, changing only the values given. Returns a 404 error if the order does not exist.

DELETE /:id

Requires admin status.

Removes an order with id :id. Returns a 404 error if the order does not exist.

eshop-backend-base's People

Contributors

jonisavo avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.