Git Product home page Git Product logo

react-news's Introduction

React-News

About

Note: Due to the popularity of this project, I am bumping up against the limits of my Firebase account. If it's unresponsive, that's probably why. If you fork the project, please sign up for a free Firebase account and update the URL in util/constants.js!

This is a real-time Hacker News clone written using React, RefluxJS, and a Firebase backend.

Demo

React-News

Demo available here.

Test User Login:
email: [email protected]
password: henleyedition1

Development and Build Process

To start the development server, run npm i && npm start and have at the src/. Files are served from /build.

Command Description
npm start Starts development server with hot reloading.
npm run build Runs development build. Outputs files to /build.
npm run dist Runs production build. Outputs files to /dist.
npm run lint Runs eslint on the /src folder.
npm test Runs test suite once.
npm run test:watch Runs test server.

Testing

Note: tests are a work in progress.

The test suite is run using npm test and npm run test:watch. Individual unit tests live in __tests__ directories throughout src/. Tests are built with Karma (test runner), Mocha (test environment), PhantomJS (test browser), Chai (assertions), and Sinon (spies/mocks). Jest was ruled out for reasons.

Firebase Structure

$ are Firebase-generated unique IDs.

├── comments
│   └── $commentId
│       ├── creator (username)
│       ├── creatorUID ($userId)
│       ├── postId ($postId)
│       ├── postTitle
│       ├── text
│       ├── time
│       └── upvotes
├── posts
│   └── $postId
│       ├── commentCount
│       ├── creator (username)
│       ├── creatorUID ($userId)
│       ├── time
│       ├── title
│       ├── upvotes
│       └── url
└── users
    └── $userId
        ├── md5hash
        ├── upvoted
        │   └── $itemId ($postId or $commentId)
        └── username

Firebase Security Rules

{
  "rules": {

    "posts": {
      // anyone can view posts
      ".read": true,
      ".indexOn": ["upvotes", "creatorUID", "commentCount", "time"],

      "$id": {
        // auth can't be null to make/edit post
        // if the post exists, auth.uid must match creatorUID
        ".write": "(auth != null && !data.exists()) || data.child('creatorUID').val() === auth.uid",

        // make sure all 5 fields are present before saving a new post
        // leave 'isDeleted' when deleting a post
        ".validate": "newData.hasChildren(['title', 'url', 'creator', 'creatorUID', 'time']) ||
                      newData.hasChildren(['isDeleted'])",

        // title must be a string with length>0
        "title": {
          ".validate": "newData.isString() && newData.val().length > 0"
        },
        "url": {
          ".validate": "newData.isString()"
        },
        "creator": {
          ".validate": "newData.isString()"
        },
        "creatorUID": {
          ".validate": "auth.uid === newData.val() && root.child('users/' + newData.val()).exists()"
        },
        "commentCount": {
          // commentCount must be writable by anyone logged in
          ".write": "auth != null",
          // 1st line: initial write
          // 2nd line: only alterable by 1
          // 3rd line: if deleted
          ".validate": "(!data.exists() && newData.val() === 1) ||
                        (newData.val() - data.val() === 1 || newData.val() - data.val() === -1) ||
                        !newData.exists()"
        },
        "upvotes": {
          // upvotes must be writable by anyone logged in
          ".write": "auth != null",
          // 1st line: initial write
          // 2nd line: cannot go below 0 and only alterable by 1
          ".validate": "(!data.exists() && newData.val() === 1) ||
                        (newData.val() >= 0 && (newData.val() - data.val() === 1 || newData.val() - data.val() === -1))"
        }
      }
    },

    "comments": {
      ".read": true,
      ".indexOn": ["postId","creatorUID","time"],

      "$comment_id": {
        ".write": "auth != null && (!data.exists() || data.child('creatorUID').val() === auth.uid)",
        ".validate": "newData.hasChildren(['postId', 'text', 'creator', 'creatorUID', 'time']) &&
                      (newData.child('text').isString() && newData.child('text').val() != '')",

        "upvotes": {
          // upvotes must be writable by anyone logged in
          ".write": "auth != null",
          // 1st line: initial write
          // 2nd line: cannot go below 0 and only alterable by 1
          ".validate": "(!data.exists() && newData.val() === 1) ||
                        (newData.val() - data.val() === 1 || newData.val() - data.val() === -1)"
        }
      }
    },

    "users": {
      ".read": true,
      ".indexOn": ["username"],

      "$uid": {
        // user not authenticated until after profile is created
        ".write": "!data.exists()",
        ".validate": "newData.hasChildren(['username', 'md5hash']) &&
                      newData.child('username').isString() &&
                      newData.child('md5hash').isString()",
        "upvoted": {
          "$itemId": {
            ".write": "auth.uid === $uid"
          }
        },
        "submitted": {
          "$itemId": {
            ".write": "auth.uid === $uid"
          }
        }
      }
    },

    // Don't let users post to other fields
    "$other": { ".validate": false }

  }
}

Firebase Authentication

To set up users, from your Firebase dashboard:

  1. Click Auth
  2. Click users
  3. Enable Email/password sign-in method

react-news's People

Contributors

aherriot avatar echenley avatar juniorbird avatar pandaiolo avatar wescravens 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.