Demo project

This is an example of my current (3 years ago) coding abilities.

It's a customer service ticketing application where customers can ask for help and the customer service agent can reply to a customer. The administrator can manage everything.

The application is deployed at Heroku https://customer-service.herokuapp.com. You can register with any fictional email you want.

If you want to check the administrative interface or change the role of your user, you can use admin@cs login and admin password. But please leave this admin as admin ;), so everyone can try this.

Front-end is an SPA built with React, Redux and React Router. Integration of back- and front-end via Webpack is provided by React-on-rails gem.

The back-end is a Rails application used mainly as an API endpoint. Business logic is encapsulated in operations powered by Trailblazer gem.

The code is tested with RSpec and Lab/Enzyme.

Site markup is adaptive. No CSS framework is used. All styles are developed especially for this project.

Authentication

API uses JWT (JSON Web Tokens) specification for authentication. API can be used not only by web-application, where it can use cookies to save session but any external application which has no cookies capabilities (mobile for example).

Application interacting with API should first login with user email and password. API checks if the user provides correct credentials, and returns temporary JWT token and “refresh” token.

The application doesn’t store plain passwords and tokens in the database for security reasons. Instead, it stores digests generated by the bcrypt library. Generating bcrypt digests is intentionally time(CPU)-demanding (to protect from brute force attacks), so we have to use JWT as lightweight and server-signed storage for credentials and authentication token on each API request.

JWTs can’t be revoked from the client, but we can set a reasonable short amount of time in which JWT is expired. Just before expiration client requests new JWT using “refresh” token, which is stored as bcrypt digest on the server. We can delete the compromised “refresh” token. And after JWT expiration client will be forced to provide credentials (email and password) to regain access.

Front-end Application

Front-end application built around a centralized store using unidirectional data flow provided by the Redux library. The centralized store contains the state of an application and uses actions to modify state with reducers.

The current state of the application is represented on the page by components that are rendered by the React library. React components are logicless and only serve as the functional transformations of application state into HTML markup.

Application logic is provided by actions, that are called by components in response to user actions. Asynchronous actions are supported by the redux-thunk library.

Actions are processed with reducers. Reducer is a function that modifies the application state in response to an action. Modified application state used by React components to represent changes to the user.

Rails API (back-end)

The API server is built using Ruby on Rails framework for routing, controllers, models and assets pipeline.

Models and controllers are logicless. Models only serve as a data access layer. Controllers only translate HTTP requests into operation calls.

Application logic is provided by operations. They are built using Trailblazer gem. It provides a unified interface for the validation of input parameters and response representation.

Integration of back-end and front-end

The only reason I do not use Rails in strict API-mode is React-on-Rails gem. This gem provides the infrastructure for using node modules and webpack transformations inside of the Rails assets pipeline. It uses a webpack to build client JavaScript file which contains React components and is referenced inside the application.js file served by assets pipeline.

In real life, I’d build a front-end application independently and serve it from CDN. But this requires too many additional steps for a simple evaluation project. One of the additional steps will be using rack-cors gem so the application can be served from the main domain and API from the api subdomain.

Also, the application can benefit from real-time updates that can be provided via ActionCable or third-party services.