
User Authentication
VinFlix uses custom frontend routes and real-time error handling to prevent access to any feature without verification

Upon account creation, passwords are hashed using the BCrypt function and a randomized session cookie is stored on the client-side browser. When logging in, the user sends a request to the server with the non-plaintext password in the header. If the password and browser cookie match, they are granted access. Passwords are never stored in plaintext and the cookie is reassigned at every login. Shown below is the User model and the different methods attached to each instance.
class User < ApplicationRecord
validates :email, :password_digest, :session_token, presence: true
validates :email, :session_token, uniqueness: true validates :password, length: { minimum: 4, maximum: 60, allow_nil: true }
validates :email, format: { with: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i, on: :create } #Uses regex to validate email format
attr_reader :password
after_initialize :ensure_session_token
def self.find_by_credentials(email, password)
user=User.find_by(email: email)
return nil unless user && user.is_password?(password)
end
def password=(password)
@password=password
self.password_digest=BCrypt::Password.create(password)
end
def is_password?(password)
BCrypt::Password.new(self.password_digest).is_password?(password)
end
def reset_session_token!
self.session_token=SecureRandom.urlsafe_base64(16)
self.save!
self.session_token
end
private
def ensure_session_token
self.session_token ||=SecureRandom.urlsafe_base64(16)
end
end
React/Redux
The user interface is managed via a collection of React.js components each with their own individual state. Redux.js is used to direct the global state of the web application as well as pass pertinent information to specific components. Shown below is the VideoIndex component and it's respective subcomponents.

When changes are made to the global state, I implemented the five step Redux cycle. First, I coded a backend utilities file which would perform an Ajax request in order to receive information stored in the database. Second, based on the user's interactions with the UI, I designed and dispatched an action. Third, my thunk middleware intercepts every action. If the action is a function (Ajax request), it is sent to my backend. If the action is an object, a "promise" is returned and sent to my reducer. Fourth, I structure a reducer which receives dispatched actions and acts as the blueprint of how the store should be changed. Fifth and finally, I create a store to, quite literally, store my global state.

Amazon Web Services/Heroku
As a data-heavy application, I chose to use AWS S3 to store my large video files. I started by creating a S3 bucket, filling it with mp4 files, configuring the security policies, and writing a seed file that links mp4 files with specific database entries. Afterwards, I installed the "Active Storage" gem, migrated changes to my database to allow files stored in the cloud to be attached to Rails models, and updated my app's credential file with my key. Shown below is my VinFlix-dev bucket. No, it's no longer public.

After downloading the CLI, migrating my static assets to a Asset Pipeline, installing webpack, and ensuring my application is production-ready, I used Heroku to host my application. I frequently monitor the metrics and Heroku logs to check on my baby.
Custom Video Player
When a video is selected, Vinflix's custom video player is opened. Using JavaScript event listeners, React refs, and the HTML5 video element, the player features volume toggling, custom seeking (fast-forward/rewind) functionality, an input bar to represent your place in the video, and a dynamically changing UI based on how user's interact with the video.

Modern Styling
Using the most up-to-date CSS3 tools and the WebKit rendering engine, VinFlix attempts to replicate Netflix's extravagant styling down to the pixel. While styling, user experience was placed on the forefront. Complex add-ons like automatically zooming in and playing videos upon hover, adding a scroll bar to see each video in a specific category, video information popping up when a video is paused, and real-time error handling all add a professional element to how a user can interact with the application. Shown below are some of my favorites.
