Integrating Omniauth for Github

Hey!

A good news for you! Our Github Editor is on its  way! In Today’s post, I am going to discuss integrating omniauth for Github using Devise gem in Ruby On Rails.

Omniauth is basically a library that standardizes the authentication for our web application. You might have seen on the various application while you are log in there is a special feature which allows you to login in from Google or from Facebook or GitHub!. You don’t have to sign up again and again just click on it and log in from somewhere else.

So Here I am going to tell you about. How to integrate it in Ruby On Rails application.

Prerequisite,

Before moving on to Omni auth, You have to integrate Devise Authentication in your app

Simple Steps to integrate omniauth in Ruby On Rails app
First Step is to add gem in gemfile
gem 'omniauth-github'

Here we will use github but you can add omniauth for other apps also like facebook or google just replace github with any of this Stratergies

Next up, you should add the columns “provider” (string) and “uid” (string) to your User model.

rails g migration AddOmniauthToUsers provider:string uid:string
rake db:migrate

Next, Declare the provider in your

config/initializers/devise.rb:

config.omniauth :github, "APP_ID", "APP_SECRET", scope: 'user,public_repo

and replace APP_ID and APP_SECRET with your app id and secret.

You can generate App ID and secret from your Github account

After configuring your strategy, you need to make your model

app/models/user.rb

devise :omniauthable, :omniauth_providers => [:github]

Then add,

Then update your routes in config/routes.rb,
devise_for :users, :controllers => { :omniauth_callbacks =>"users/omniauth_callbacks" }

Now add the file

app/controllers/users/omniauth_callbacks_controller.rb:


class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
end

The callback should be implemented as an action with the same name as the provider like this,

class Users::OmniauthCallbacksController :authentication #this will throw if @user is not activated
set_flash_message(:notice, :success, :kind => "Github") if is_navigational_format?
else
session["devise.github_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end

def failure
redirect_to root_path
end
end

This action has a few aspects worth describing:

When a valid user is found, they can be signed in with one of two Devise methods: sign_in or sign_in_and_redirect. Passing :event => :authentication is optional. You should only do so if you wish to use Warden callbacks.

After the controller is defined, we need to implement the from_omniauth method in our model

app/models/user.rb

:

def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name # assuming the user model has a name
user.image = auth.info.image # assuming the user model has an image
# If you are using confirmable and the provider(s) you use validate emails,
# uncomment the line below to skip the confirmation emails.
# user.skip_confirmation!
end
end

This method tries to find an existing user by the provider and uid fields. If no user is found, a new one is created with a random password and some extra information.

Notice that Devise’s RegistrationsController by default calls User.new_with_session before building a resource. This means that, if we need to copy data from session whenever a user is initialized before sign up, we just need to implement new_with_session in our model. Here is an example that copies the github email if available

class User < ApplicationRecord
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end

For more infor you can go to Documentation
 And here you are done. 🙂
Leave Comments if you are getting any trouble.
I am always ready for help!
Keep Rocking!

Advertisements

An Annoying Github Commit[Github API]

Relax! Relax! Relax!
Don’t worry I won’t annoy you!
Github API, If you are dealing first time with this then be ready to face, But Wait Wait Wait What I am doing here? Obviously, I am here to help you! Let me make it simpler for you. 😀

Now to make a commit using commands is very easy what you have to do is

$git add -A #this will add the files which you are going to commit
$git commit -m "message" #This will make a commit locally!
$git push origin master

that’s it you are done!

Now as you know I am working on Editor basically Github editor I have to fetch repository and then commit back to the master repo on Github. For this purpose, We have to use a Github API
Here, You see Http requests are transfering like Get request or Post Request. Now you might wonder how we can do this in Rails. It is very simple. Just Focus!

There are 2 ways to do that
1. Using Rest Client
2. Using rails github-api gem

REST Client
This will help you in making GET and POST request directly to the API and API will Respond accordingly.
Now Generally to make a Commit you have to follow few steps
which is very well and beautifully explained by levibotelho

Github-API Gem
This is a Ruby client for the official GitHub API.
Installation
Fitst, Open Gemfile and add
gem "github_api"
And then Run

$bundle install

Now, How to make a Commit

In order to be able to commit (create/update/remove) files you need to use Contents API like so:

contents = Github::Client::Repos::Contents.new oauth_token: '...'

Having instantiated the contents, to create a file do:

contents.create 'username', 'repo_name', 'full_path_to/file.ext',
path: 'full_path_to/file.ext',
message: 'Your commit message',
content: 'The contents of your file'

Content is all Base64 encoded to/from the API, and when you create a file it encodes it automatically for you.

To update a file, first you need to find the file so you can get the SHA you’re updating off of:

file = contents.find path: 'full_path_to/file.ext'

Then update the file just like you do with creating:

contents.update 'username', 'repo_name', 'full_path_to/file.ext',
path: 'full_path_to/file.ext'
message: 'Your commit message',
content: 'The contents to be updated',
sha: file.sha

That’s It This will commit ur changes in Remote Repository!
The First method is laborous as you have to perform each step manually. But This Gem makes our life easiear.
I’ll love to here your views in comments.
Keep Rocking! 😀

Save Content of Ace in Rails

As I told you we are making an Editor. So we have to save the file after editing.

There are a number of ways to do this. I am doing it using Ajax.
For this, we need
1. filename or location
2. Content
to save a file. But the twist is we are using Ajax editor. Ace editor is a javascript editor so it performs operations only in javascript file
So what I have done is to Get content and location from the app and then send it to the controller using Ajax. Here, Ajax play’s a very important role. Let’s be more technical!

first of all, save button

create a save button in HTML with attribute class=”save button”

then javascript
$('.save-button').click(function(){
var name = "editor-" + $("#tabs-editor> .current").attr("id"); // This will store the location of editor
var editor=ace.edit(name);
var content= editor.getSession().getValue();// This will get the content of the eidtor which is editted
$file.push($("#tabs-editor > .current").attr("id")) // This is simple editor storing all files location which is edited
$.ajax({ // Ajax call
url: "filedata", //url
type: "post", //method
data: { //data to be sent
"file" :$("#tabs-editor> .current").attr("id"),
"content" : content
},
dataType: JSON,
success: function(data){ //On success
alert('successfully');
}
});
});

We will attach data attribute only when we have to send data to the controller

Now Routes will get the url “filedata” and perform the action which is specified to it by transferring control in controller

for that let’s edit routes.rb

post 'gitrepos/filedata', to: 'gitrepos#filedata'

then here controller is gitrepos
the action is filedata

def filedata
name = {}
request.POST.each do |key, value|
name[key] = value
end
puts name['file']
f = File.open(name['file'], 'w')
f.write(name['content'])
f.close
end

That’s it

HTML Parser in Editor

Now Think of an editor which can show output as well. Sounds amazing? what if Instantly we get the output of whatever we write or code in any language. This seems to be an amazing task so let’s do it!

Let’s start from HTML

whatever we write using HTML tags immediately we get output in the browser. Their are multiple ways to do that but we are lazy one :p . So, let’s do in a simpler way.

Now Think how we can do this?

let me tell you, we just have to open the html file using a tag and show it into new tab simple. Now let’s be more technical.

First, create an a tag with attribute target=”_blank”

target=”_blank”- This will open the file in new tab

now Javascript

  $(“.compile”).attr(‘href’,”location”);

I just added the attribute href dynamically with location of the file;

location is like “uploads/extract/:id/:upload_file_name”

and it redirects at https://localhost:3000/uploads/extract/1/file

then how routes will configure public path? Because all the project is store in public folder

For this

edit routes in config/routes.rb

get ‘uploads/extract/:id/:upload_file_name(*all)’, to: ‘gitrepos#moveto’

it will go to controller gitrepos and action moveto

def moveto
goto = {}
request.path_parameters.each do |key, value|
goto[key] = value
end
path = “/system/repositories/github/#{goto[:id]}/#{goto[:url]}#{goto[:all]}”
redirect_to(path)
end

That’s it!

Ace Syntax Highlighter

Now I have configured Ace to work within my editor so It’s time to add the feature of Syntax Highlighter.

Generally, we’ll manually set mode to editor like

editor.mode(‘ace/mode/javascript’);

for this File extension must be known to us so that we can manually add mode but we don’t know the file extension before hand. so we have to use some intermediator which will tell the file extension.

Ace editor already have a built-in functionality

i.e modelist

now How we can use it?
1. Initialize modelist
var modelist = ace.require("ace/ext/modelist");
2. Get the mode for particular file
var mode = modelist.getModeForPath(path).mode;
3. Set the mode to editor
editor.session.setMode(mode);

That’s it, all this is done under javascript file.

 

Lightweight Fuzzy Search

A search is always needed in editor to search for a particular file or directory so for this we are using Fuse.js.
Fuse.js is a javascript library for lightweight Fuzzy search.
Now How I implemented in my app.

var files = {
keys: ['filename']
};

This will include all the files name;

var fuse = new Fuse(list, option);

and here’ we give input with options.
You can check fuse for more details.

Beautify Code

Coding should be done in a neat and clean way. Also, the code should be reusable

understandable and simple. Rails have a great feature to organize code in a very productive way in augmenting of this The atom editor is doing really a great job in Beautifying code.

Also in rails, Their is a gem named as Rubocop

To install this add

gem 'rubocop', '~> 0.49.0', require: false

then go to ur project directory and run

$rubocop

And see the maggic!