Skip to content

ioanniskousis/amitree-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Amitree Take Home Technical Challenge

This project creates an API using Ruby on Rails


Contributors Forks Stargazers Issues


Contents




About the project


The project was assigned as a Take Home Technical Challenge by the hiring process of Amitree.

The requirements

The company wants to implement a customer referral program, in order to acquire new paying customers. Here are the product requirements that we are given:

  • An existing user can create a referral to invite people, via a shareable sign-up link that contains a unique code

  • When 5 people sign up using that referral, the inviter gets $10.

  • When somebody signs up referencing a referral, that person gets $10 on signup.
    Signups that do not reference referrals do not get any credit.

  • Multiple inviters may invite the same person. Only one inviter can earn credit for a particular user signup. An inviter only gets credit when somebody they invited signs up; they do not get credit if they invite somebody who already has an account.




Solution

Ruby on Rails was used to acheive the solution. So, inintialization was performed by the command

rails new amitree-api --api --database=postgresql -T

The following models were generated:

  • user, to store user's details
  • referral, to store the referral codes the users create
  • referenced_registrations, to link each user who signs up using a referral code with the creator of the code
  • credit, to track each user's credit

The following Controllers manage the calls to the API:

  • UsersController manages the creation of new users
  • AuthenticationController manages the authenticaton of logged in users
  • ReferralsController manages the creation of new referral codes by users

The following routes consist the interface:

  • post 'register' for the creation of a new user
  • post 'authenticate' for authenticating a user
  • post 'referral' for the creation of a referral code
  • get 'users' to retreive users' index
  • get 'user/:id' to retreive a user's info

Registration

A call to the register route supplied with data for name, email, password, password confirmation and optionally a referral code is directed to the UsersController at the create method.
Appropriate validations are performed and a successful creation of a new user renders back a structure containing :

  • auth_token
  • user_id
  • user_name
  • user_email

Validations are performed on model, database, and controller levels.


Authentication

The Token-based Authentication practice is implemented so the gem jwt was hired to make encoding and decoding of HMACSHA256 tokens

The authentication token is created at the login procedure and is returned to the caller.
For this, a call to the authenticate route is required suppling data for email and password.
The data is passed to the JsonWebToken singleton class that validates and successfully creates the token to be supplied to the user. A failure of validating email or password causes the return of a 'invalid credentials' message.

The return structure includes useful data to be used by the caller. The content of returned structure:

  • auth_token
  • user_id
  • user_name
  • user_email

Referral Code creation

A call to the referral route requires the authentication token to be supplied in the header structure of the request.
The user is authenticated and a 20 characters length string is generated and returned to the caller.
If the user has already created a referral code then a 'You Already Have Created A Referral Code' message is returned.


Users Index

A call to the users route requires the authentication token to be supplied in the header structure of the request.

An array of all users is returned having each item containing the following fields:

  • id
  • name
  • email
  • credit
  • inviter
  • referral_code

User Info

A call to the user/:id route requires the authentication token to be supplied in the header structure of the request.

The following fields are returned:

  • id
  • name
  • email
  • inviter
  • credit
  • referral_code
  • invited_users: an array of users with each containing
    • id
    • name
    • email
    • credit

Test

Test units have been implemented using RSpec to test the requests agains the API.
Find the units in spec/requests/

To run tests type on the command prompt

rspec --format documentation


Interaction

Registration:

A POST request is required with body structure containing values for the following

  • name
  • email
  • password
  • password_confirmation
  • referral_code

The response can be

1. either a JSON structure:


{
  auth_token: auth_token,
  user_id: id,
  user_name: name,
  user_email: email
}

2. Or at least one of the following messages

error: {
  name: 'is too short (minimum is 4 characters)'
}

error: {
  name: 'can't be blank'
}

error: {
  email: 'is invalid'
}

error: 'email is already registered'

error: {
  password: 'is too short (minimum is 4 characters)'
}

error: {
  password: 'can't be blank'
}

error: 'password does not match password_confirmation'

error: 'Invalid Referral Code'



Authentication:

A POST request is required with body structure containing values for the following

  • email
  • password

The response can be

1. either a JSON structure:


{
  auth_token: auth_token,
  user_id: id,
  user_name: name,
  user_email: email
}

2. Or a message

error: {
  user_authentication: 'invalid credentials'
}

Referral code creation:

A POST request is required with headers structure containing

  • Authorization

Note that you have to prefix the authorization token with 'Bearer '
i.e.

headers: {
          'Authorization': 'Bearer ' + auth_token
         }

The response can be:

  1. either a JSON structure:

{
  referral_code: referral_code
}

2. Or one of these messages

{
  error: 'Not Authorized'
}

{
  constrain: 'You Already Have Created A Referral Code' 
}

Users Index

A GET request is required with header structure containing

  • Authorization

Note that you have to prefix the authorization token with 'Bearer '
i.e.

headers: {
          'Authorization': 'Bearer ' + auth_token
         }

The response can be:

  1. either an array of users with the following JSON structure:

{
  id: user_id,
  name: user_name,
  email: user_email,
  credit: user_credit,
  inviter: user_inviter,
  referral_code: user_referral
}

2. Or the unauthorized message

{
  error: 'Not Authorized'
}

User's Info

A GET request is required with header structure containing

  • Authorization

Note that you have to prefix the authorization token with 'Bearer '
i.e.

headers: {
          'Authorization': 'Bearer ' + auth_token
         }

The response can be:

  1. either the following JSON structure:

{
  id: user_id,
  name: user_name,
  email: user_email,
  inviter: user_inviter,
  credit: user_credit,
  referral_code: user_referral&.code,
  invited_users: array of the invited users
}

Note that the invited_users is an array with each element containing:

{
  id: user_id,
  name: user_name,
  email: user_email,
  credit: user_credit
}

2. Or the unauthorized message

{
  error: 'Not Authorized'
}



Deployment

The API has been deployed on heroku at this address

https://boiling-fjord-82978.herokuapp.com

In order to run the API locally,

  • clone this project from the github repository
  • run bundle
  • in a case that the database is not downloaded
    • run: rails db:migrate
  • and run the rails server

Evaluation

  1. The application does have the features to fulfill the requirements and use cases
    • Allows a user to create a referral code
    • Users that sign up using a referral code, they get $10 in credit
    • Signups that do not reference referrals do not get any credit
    • For every 5 people sign up using a referral, the inviter gets $10
    • Only one inviter can earn credit for a particular user signup since email credential is unique in the database and a user can not register twice using the same email address
  2. The code is readable and well formated since the use of rubocop gem and self-documenting with comments at parts that need explanation
  3. Automated tests are implemented that validate the functionality works as intended
  4. The solution is simple and well organized. No extra routes, models, controllers are implemented although a real app in production would require further features
  5. The code is error-resistant and does consider reasonable edge-cases
  6. The API allows a capable front-end developer to build an application.

** Please note, usually the Heroku is delaying the first call several seconds.



Contributors

👤 Author

Ioannis Kousis

About

Amitree Take Home Technical Challenge

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published