hmellor / auction-website

An open-source auction hosting system
https://hmellor.github.io/auction-website/
MIT License
106 stars 51 forks source link
auction auction-service auction-system auction-website auctionapp auctions firebase react

Auction Website

In this repo you will find the code and instructions to host an auction website for free using GitHub Pages and Firebase anonymous authentication & databases.

This is a project I originally worked on for a charity event and I've been improving it in my spare time ever since. Contributions and suggestions are welcome!

Table of contents

Features

Realtime bidding using event listeners (no need to refresh page).

Built with Bootstrap so everything is reactive:

Device based login requiring only a username to be provided (no need to store sensitive information):

Popup additional item details and an additional image (same image was used for demo):

Admin page for administrators to monitor the auction more easily and see who's winning:

Setup

Here we will cover how to add your own information to the auctions themselves, finally how to connect it all to Firebase to enable user login and bidding.

Environment

To develop and deploy your own auction, you'll need to install Node.js v21. To do this, follow the instructions here.

Then, install the required packages as follows:

npm install

You can start the development server by running:

npm run dev

You can build for production and preview the production build by running:

npm run build
npm run preview

Your website will deploy automatically using the .github\workflows\pages.yml.

Items

First, set demo = false in src/App.jsx (this stop the timers from automatically resetting).

Then, populate public\items.yml with the information for of the items you'll be putting up for auction. The fields are:

Firebase

Here we will cover how to set up your Firebase project and then how to enable the Firebase authentication and database respectively.

Creating a project

You can create a project using the following steps:

The code snippet containing firebaseConfig and the current version can be found in Project settings if you need to refer to it later.

Authentication

Head to your project's console and click on Authentication in the menu on the left. Then go to the Sign-in method tab and enable the Anonymous sign-in provider.

Anonymous authentication is tied to the user's browser. This means that if the user uses a different browser, or clears their site data, they will appear as a new user when they next sign up.

You can read more about anonymous authentication in the documentation.

Firestore Database

To set up Firestore, follow the Firestore quickstart documentation.

Next, navigate to the Rules tab and paste the following rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Checks that new data doesn't overwrite or delete an existing bid
    function isFieldOverWrite() {
      let editedKeys = request.resource.data.diff(resource.data);
      return editedKeys.changedKeys().union(editedKeys.removedKeys()).size() > 0
    }
    // Checks user has anonymous account and has "signed up" (i.e. provided a displayName)
    function isLoggedIn() {
      return request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))
    }
    // Checks the user is logged in and if their user data contains the admin password
    function isAdmin() {
      return isLoggedIn() && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == "insert long random secret string"
    }
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if isAdmin() || request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null && request.auth.uid == userId;
    }
    // Auction can always be read, updated only if the user is logged in and
    // isn't overwiting someone else's bid, and created or deleted by admins
    match /auction/items {
      allow get, list: if true;
      allow update : if isAdmin() || isLoggedIn() && !isFieldOverWrite()
      allow create, delete: if isAdmin();
    }
  }
}

These rules state that:

Creating an admin account

The final step in setting up your auction is to create an admin account and use it to initialise and monitor your auction.

To create an admin account:

Please don't reuse one of your existing passwords! While the Firestore rules should prevent bad actors from reading your user's data, don't risk it. I can't be responsible for leaked passwords due to a misconfigured project

Initialising the auction

To initialise the auctions:

The Admin page provides:

If the website is hosted:

N.B. The loading of the item data, which happens for both the update and delete buttons, can cause the buttons to be a little slow to react.