Rails API – Quick note

1. Setting up Rails 5

rails new api_app_name --api -d postgresql -T
cd api_app_name
bundle install
rails db:setup

Note:

--api : generate API app only

-d postgresql : using postgresql database

-T : to skip generating Test because we are going to use RSpec for testing.

2. Using RSpec for testing

group :development, :test do

    # Use RSpec for specs
    gem 'rspec-rails', '3.1.0'

    # Use Factory Girl for generating random test data
    gem 'factory_girl_rails'
end
bundle
rails g rspec:install

3. Building your API

rails g scaffold user name email
rails db:migrate
# run the default server on port 3000
rails s

4. Serializing API ouput

gem 'active_model_serializers'
bundle
rails g serializer user
# app/serializers/user_serializer.rb
class UserSerializer < ActiveModel::Serializer
    attributes :id, :name, :email
end

class ApplicationController < ActionController::API
    include ActionController::Serialization

    # ...
end

5. Enabling CORS (Cross-Origin Resource Sharing)

gem 'rack-cors'
bundle
# config/application.rb
module YourApp
    class Application < Rails::Application

    # ...

    config.middleware.insert_before 0, "Rack::Cors" do
        allow do
        origins '*'
        resource '*', :headers => :any, :methods => [:get, :post, :options]
        end
    end

    end
end

6. Versioning your API

# GET http://api.mysite.com/v1/users/

app/controllers/
.
|-- api
|   |-- v1
|       |-- api_controller.rb
|       |-- users_controller.rb
|-- application_controller.rb
# app/controllers/api/v1/api_controller.rb
module Api::V1
    class ApiController < ApplicationController
    # Generic API stuff here
    end
end
# app/controllers/api/v1/users_controller.rb
module Api::V1
    class UsersController < ApiController

    # GET /v1/users
    def index
        render json: User.all
    end

    end
end
# config/routes.rb
constraints subdomain: 'api' do
    scope module: 'api' do
    namespace :v1 do
        resources :users
    end
    end
end

7. Rate Limiting and Throttling

gem 'rack-attack'
bundle
# config/application.rb
module YourApp
    class Application < Rails::Application
    # ...
    config.middleware.use Rack::Attack
    end
end
# config/initializers/rack_attack.rb
class Rack::Attack

    # `Rack::Attack` is configured to use the `Rails.cache` value by default,
    # but you can override that by setting the `Rack::Attack.cache.store` value
    Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new

    # Allow all local traffic
    whitelist('allow-localhost') do |req|
    '127.0.0.1' == req.ip || '::1' == req.ip
    end

    # Allow an IP address to make 5 requests every 5 seconds
    throttle('req/ip', limit: 5, period: 5) do |req|
    req.ip
    end

    # Send the following response to throttled clients
    self.throttled_response = ->(env) {
    retry_after = (env['rack.attack.match_data'] || {})[:period]
    [
        429,
        {'Content-Type' => 'application/json', 'Retry-After' => retry_after.to_s},
        [{error: "Throttle limit reached. Retry later."}.to_json]
    ]
    }
end

8. Authenticating your API

Authorization: Token token="WCZZYjnOQFUYfJIN2ShH1iD24UHo58A6TI"
rails g migration AddApiKeyToUsers api_key:string

class User < ActiveRecord::Base

    # Assign an API key on create
    before_create do |user|
    user.api_key = user.generate_api_key
    end

    # Generate a unique API key
    def generate_api_key
    loop do
        token = SecureRandom.base64.tr('+/=', 'Qrt')
        break token unless User.exists?(api_key: token)
    end
    end
end
#  using the built in authenticate_or_request_with_http_token Rails method.
class ApplicationController < ActionController::Base
    include ActionController::HttpAuthentication::Token::ControllerMethods

    # Add a before_action to authenticate all requests.
    # Move this to subclassed controllers if you only
    # want to authenticate certain methods.
    before_action :authenticate

    protected

    # Authenticate the user with token based authentication
    def authenticate
        authenticate_token || render_unauthorized
    end

    def authenticate_token
        authenticate_with_http_token do |token, options|
            @current_user = User.find_by(api_key: token)
        end
    end

    def render_unauthorized(realm = "Application")
        self.headers["WWW-Authenticate"] = %(Token realm="#{realm.gsub(/"/, "")}")
        render json: 'Bad credentials', status: :unauthorized
    end
end
# test
curl -H "Authorization: Token token=PsmmvKBqQDOaWwEsPpOCYMsy" http://localhost:3000/users

Setup Ubuntu Server

After my server on DigitalOcean was attacked few times, I thought I should write an article about it. Do hope it is useful to you.

Step One — Root Login

 $ ssh root@your_server_ip

Step Two — Create a New User

 # adduser van

Step Three — Root Privileges

Set root privileges to new user.

 # usermod -aG sudo van

Step Four — Add Public Key Authentication (Recommended)

Generate a Key Pair

You need to generate a key pair on your local machine before putting it on the server.

 $ ssh-keygen
ssh-keygen output
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/localuser/.ssh/id_rsa):

You will be asked a few questions. It is recommended to leave the password field blank.

Copy the Public Key manually

On your local machine, type the command below will show your public key inside terminal.

 $ cat ~/.ssh/id_rsa.pub

Now copy it to the clipboard.

id_rsa.pub contents
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBGTO0tsVejssuaYR5R3Y/i73SppJAhme1dH7W2c47d4gOqB4izP0+fRLfvbz/tnXFz4iOP/H6eCV05hqUhF+KYRxt9Y8tVMrpDZR2l75o6+xSbUOMu6xN+uVF0T9XzKcxmzTmnV7Na5up3QM3DoSRYX/EP3utr2+zAqpJIfKPLdA74w7g56oYWI9blpnpzxkEd3edVJOivUkpZ4JoenWManvIaSdMTJXMy3MtlQhva+j9CgguyVbUkdzK9KKEuah+pFZvaugtebsU+bllPTB0nlXGIJk98Ie9ZtxuY3nCKneB+KjKiXrAvXUPCI9mWkYS/1rggpFmu3HbXBnWSUdf localuser@machine.local

Next, connect to your server as root user. Then switch to your sudo user.

 # su - van

Create .ssh folder.

 $ mkdir ~/.ssh
 $ chmod 700 ~/.ssh

Create authorized_keys file.

 $ nano ~/.ssh/authorized_keys

When the authorized_keys file opened. Let’s paste your public key here. Then press Ctrl-o to save the file and Ctrl-x to close it.

It’s better to restrict access privileges of this file.

 $ chmod 600 ~/.ssh/authorized_keys

Exit sudo user.

 $ exit

Step Five — Disable Password Authentication (Recommended)

Let’s open sshd_config file.

 $ sudo nano /etc/ssh/sshd_config

To disable password authentication, you need to set no to PasswordAuthentication directive.

PasswordAuthentication no

Then to make sure, you should check these default settings are correct.

PubkeyAuthentication yes
AuthorizedKeyFile  .ssh/authorized_keys
ChallengeResponseAuthentication no

Apply update sshd_config.

 $ sudo systemctl reload sshd

Step Six — Test Log In

It’s time to check if everything is working nicely. Let’s connect to your server with the new sudo user.

 $ ssh van@your_server_ip
 $ sudo command_to_run

Step Seven — Set Up a Basic Firewall

 $ sudo ufw enable
 $ sudo ufw allow OpenSSH
 $ sudo ufw status
Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

Step Eight — Disable Root Login (Recommended)

To prevent server attack, it’s recommended to disable root login.

 $ sudo nano /etc/ssh/sshd_config

To disable root login, you just need to set no to PermitRootLogin directive.

PermitRootLogin no

What Next

These steps are the foundation of server setup. Now you can install any softwares on your new server.

To keep your server more secure, you could have a look at fail2ban solution or changing your ssh port. At the moment, I have just changed my ssh port. It works for now.

Happy coding!

References
https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-14-04
https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04

How to Display an Animated gif in React Native

By default the Gif images are not supported in android react native app. You need to set the following code to display the gif images.

Open your android/app/build.gradle file add the following code:

open android/app/build.gradle add the following  code 

dependencies: { 
  ...
     // For animated GIF support
    compile 'com.facebook.fresco:animated-base-support:0.11.0'  
    // For WebP support, including animated WebP
    compile 'com.facebook.fresco:animated-gif:0.11.0'  
    compile 'com.facebook.fresco:animated-webp:0.11.0' 
    compile  'com.facebook.fresco:webpsupport:0.11.0'  

Then you need to bundle the app again.

References: Image component stackoverflow.com

Install Atom Text Editor on Ubuntu 16.04

How to install Atom in Ubuntu via PPA:

Webupd8 Team is maintaining an unofficial PPA with most recent Atom packages for all current Ubuntu releases, and derivatives. While official Linux binary is 64-bit only, the PPA supports both 32-bit and 64-bit.

1. Add PPA

Open terminal (Ctrl+Alt+T) and run the command:

$ sudo add-apt-repository ppa:webupd8team/atom

2. Update and install Atom editor:

Update system package index and install the text editor via command:

$ sudo apt update; sudo apt install atom

Once Atom is installed and a new release is out in future, you can simply upgrade the editor by running regular system updates via Software Updater utility.

3. (Optional) To remove Atom text editor

To remove the software, use Synaptic Package Manager or just run apt command with remove flag:

$ sudo apt remove --purge atom

And the PPA can be remove via Software & Updates utility under Other Software tab.

References: tipsonubuntu.com

How to Uninstall Android Studio 2.2 on Ubuntu 16.04

  1. Delete the android-studio folder;
  2. Delete the sdk folder if it is in not inside the android-studio directory;
  3. Delete ~/.AndroidStudio2.2/, which contains config and system;
  4. Delete ~/.android;
  5. Delete ~/.local/share/applications/jetbrains-studio.desktop, if you created a shortcut using Configure->Create Desktop Entry.

Note:

The android-studio folder is normally in /usr/local/ for your user profile, or /opt/ for shared users.

The sdk folder is normally at ~/Android.

References: askubuntu.com