Created
March 2, 2017 16:32
-
-
Save diegomelo182/76385da60772b6f4f409df8fa4965cb1 to your computer and use it in GitHub Desktop.
Angular 2 - Rest API Service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ApplicationController < ActionController::API | |
before_action :jwt_auth_validation | |
def jwt_auth_validation | |
jwt_token = request.headers['Authentication'] | |
if jwt_token | |
token_decoded = jwt_decode(jwt_token) | |
if !token_decoded.first.nil? && !token_decoded[0][:auth].nil? && token_decoded[0][:auth] | |
render json: { error: 'Authentication error, token is wrong on header Authentication' }, status: :unauthorized | |
return; | |
elsif !token_decoded.first.nil? && !token_decoded[0][:exp].nil? && token_decoded[0][:exp] | |
render json: { error: 'Authentication error, token expired.' }, status: :unauthorized | |
return; | |
elsif token_decoded.length>1 && jwt_invalid_payload(token_decoded[0]) | |
render json: { error: 'Authentication error, invalid payload.' }, status: :unauthorized | |
return; | |
elsif token_decoded.length>1 && !jwt_invalid_payload(token_decoded[0]) && token_decoded[0]['request_type'] == 'password_recovery' | |
# password recovery token verification | |
unless request.original_fullpath.index('/users/'+token_decoded[0]['user_id'].to_s) == 0 | |
render json: { error: 'Permission error, action unauthorized.' }, status: :unauthorized | |
return; | |
end | |
end | |
# renew token | |
if token_decoded.length>1 | |
renewed_payload = token_decoded.first | |
if !renewed_payload['exp'].nil? | |
time_start = Time.at(renewed_payload['exp']) - 1.hours | |
time_end = Time.at(renewed_payload['exp']) | |
time_now = Time.now.to_i | |
if time_now >= time_start.to_i && time_now <= time_end.to_i | |
renewed_payload['exp'] = 4.hours.from_now.to_i | |
response.headers['JWT-Token-Renewed'] = jwt_encode(renewed_payload) | |
end | |
end | |
end | |
else | |
render json: { error: 'Authentication error, token is missing on header Authentication' }, status: :unauthorized | |
return; | |
end | |
end | |
private | |
def jwt_decode(token, secure = true) | |
begin | |
if secure | |
token = JWT.decode token, Rails.application.secrets.hmac_secret, true, { :algorithm => 'HS256' } | |
else | |
token = JWT.decode token, nil, false | |
end | |
rescue JWT::ExpiredSignature | |
token = [ { exp: true, auth: false } ] | |
rescue | |
token = [ { exp: false, auth: true } ] | |
end | |
return token | |
end | |
def jwt_encode(payload, secure = true) | |
if secure | |
return JWT.encode payload, Rails.application.secrets.hmac_secret, 'HS256' | |
end | |
return JWT.encode payload, nil, 'none' | |
end | |
def jwt_invalid_payload(payload) | |
return (!payload['token_type'].nil? && payload['token_type'] != 'client_a2') || (!payload['token_type'].nil? && payload['token_type'] != 'client_a2' && !payload['request_type'].nil? && payload['request_type'] != 'password_recovery') | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { Router } from '@angular/router'; | |
import { Http, Response, Headers, RequestOptionsArgs } from '@angular/http'; | |
import { Observable } from 'rxjs/Rx'; | |
import { LocalStorageService } from 'angular-2-local-storage'; | |
import 'rxjs/add/operator/toPromise'; | |
import { | |
AppHelper, | |
AppConstants | |
} from '../helpers'; | |
export class DefaultService { | |
public endPoint: string; | |
constructor( | |
public http: Http, | |
public localStorageService: LocalStorageService, | |
public router: Router, | |
) { } | |
// GET /end-point | |
public getAll(query_object: any = {}): Observable<any> { | |
let url = AppConstants.wpApiDevUrl+this.endPoint; | |
let params = query_object ? '?'+AppHelper.objectToQueryString(query_object) : ''; | |
// JWT | |
let options: RequestOptionsArgs = { headers: this.getJWTHeaders() }; | |
return this.http.get(url+params, options) | |
.map((res: Response): Observable<any> => { | |
this.setJWTHeaders(res); // renew token | |
let response; | |
if(res.text()) { | |
response = res.json(); | |
} | |
return response || {}; | |
}) | |
.catch((error: Response | any) => { | |
return Observable.throw(error); | |
}); | |
} | |
// GET /end-point/:id | |
public getById(id: number, query_object: any = {}): Observable<any> { | |
let url = AppConstants.wpApiDevUrl+this.endPoint+'/'+id; | |
let params = '?'+AppHelper.objectToQueryString(query_object); | |
// JWT | |
let options: RequestOptionsArgs = { headers: this.getJWTHeaders() }; | |
return this.http.get(url+params, options) | |
.map((res: Response): Observable<any> => { | |
this.setJWTHeaders(res); // renew token | |
let response; | |
if(res.text()) { | |
response = res.json(); | |
} | |
return response || {}; | |
}) | |
.catch((error: Response | any) => { | |
return Observable.throw(error); | |
}); | |
} | |
// POST /end-point/ | |
public create(query_object: any = {}): Observable<any> { | |
let url = AppConstants.wpApiDevUrl+this.endPoint; | |
let params = JSON.stringify(query_object); | |
// JWT | |
let options: RequestOptionsArgs = { headers: this.getJWTHeaders() }; | |
return this.http.post(url, params, options) | |
.map((res: Response): Observable<any> => { | |
this.setJWTHeaders(res); // renew token | |
let response; | |
if(res.text()) { | |
response = res.json(); | |
} | |
return response || {}; | |
}) | |
.catch((error: Response | any) => { | |
return Observable.throw(error); | |
}); | |
} | |
// PUT /end-point/:id | |
public update(id: number, query_object: any = {}): Observable<any> { | |
let url = AppConstants.wpApiDevUrl+this.endPoint+'/'+id; | |
let params = JSON.stringify(query_object); | |
// JWT | |
let options: RequestOptionsArgs = { headers: this.getJWTHeaders() }; | |
return this.http.put(url, params, options) | |
.map((res: Response): Observable<any> => { | |
this.setJWTHeaders(res); // renew token | |
let response; | |
if(res.text()) { | |
response = res.json(); | |
} | |
return response || {}; | |
}) | |
.catch((error: Response | any) => { | |
return Observable.throw(error); | |
}); | |
} | |
// DELETE /end-point/:id | |
public delete(id: number): Observable<any> { | |
let url = AppConstants.wpApiDevUrl+this.endPoint+'/'+id; | |
// JWT | |
let options: RequestOptionsArgs = { headers: this.getJWTHeaders() }; | |
return this.http.delete(url, options) | |
.map((res: Response): Observable<any> => { | |
this.setJWTHeaders(res); // renew token | |
let response; | |
if(res.text()) { | |
response = res.json(); | |
} | |
return response || {}; | |
}) | |
.catch((error: Response | any) => { | |
return Observable.throw(error); | |
}); | |
} | |
// DELETE /your-url | |
public getDataByUrl(urlRequest: string, getParams: any = {}): Observable<any> { | |
let url = AppConstants.wpApiDevUrl+urlRequest; | |
let params = '?'+AppHelper.objectToQueryString(getParams); | |
// JWT | |
let options: RequestOptionsArgs = { headers: this.getJWTHeaders() }; | |
return this.http.get(url+params, options) | |
.map((res: Response): Observable<any> => { | |
this.setJWTHeaders(res); // renew token | |
let response; | |
if(res.text()) { | |
response = res.json(); | |
} | |
return response || {}; | |
}) | |
.catch((error: Response | any) => { | |
return Observable.throw(error); | |
}); | |
} | |
// POST /your-url | |
public postDataByUrl(urlRequest: string, getParams: any = {}): Observable<any> { | |
let url = AppConstants.wpApiDevUrl+urlRequest; | |
let params = JSON.stringify(getParams); | |
// JWT | |
let options: RequestOptionsArgs = { headers: this.getJWTHeaders() }; | |
return this.http.post(url, params, options) | |
.map((res: Response): Observable<any> => { | |
this.setJWTHeaders(res); // renew token | |
let response; | |
if(res.text()) { | |
response = res.json(); | |
} | |
return response || {}; | |
}) | |
.catch((error: Response | any) => { | |
return Observable.throw(error); | |
}); | |
} | |
// set JWT Header | |
private getJWTHeaders(): Headers { | |
return new Headers({ | |
'Content-Type': 'application/json', | |
'Authentication': this.localStorageService.get('token'), | |
}); | |
} | |
// get JWT Header | |
private setJWTHeaders(response: Response): void { | |
if(response.headers.get('JWT-Token-Renewed')){ | |
this.localStorageService.set('token', response.headers.get('JWT-Token-Renewed')); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { Http, Response } from '@angular/http'; | |
import { Observable } from 'rxjs/Rx'; | |
import { LocalStorageService } from 'angular-2-local-storage'; | |
import { Router } from '@angular/router'; | |
import { DefaultService } from './default.service'; | |
@Injectable() | |
export class UsersService extends DefaultService { | |
public endPoint: string = 'users'; | |
constructor( | |
public http: Http, | |
public localStorageService: LocalStorageService, | |
public router: Router, | |
) { | |
super(http, localStorageService, router); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UsersController < ApplicationController | |
before_action :set_user, only: [:show, :update, :destroy] | |
skip_before_action :jwt_auth_validation, only: [:login, :logoff, :recovery_password] | |
# GET /users | |
# GET /users.json | |
def index | |
@users = User.eager_load(:rule) | |
render json: @users | |
end | |
# GET /users/1 | |
# GET /users/1.json | |
def show | |
render json: @user | |
end | |
# POST /users | |
# POST /users.json | |
def create | |
@user = User.new(user_params) | |
if @user.valid? | |
if @user.save | |
UsersMailer.create(@user, params[:user][:password]).deliver_later | |
render json: @user, status: :created, location: @user | |
else | |
render json: @user.errors, status: :unprocessable_entity | |
end | |
else | |
render json: @user.errors, status: :unprocessable_entity | |
end | |
end | |
# PATCH/PUT /users/1 | |
# PATCH/PUT /users/1.json | |
def update | |
@user = User.find_by(id: params[:id]) | |
if @user.update(user_params) | |
head :no_content | |
else | |
render json: @user.errors, status: :unprocessable_entity | |
end | |
end | |
# DELETE /users/1 | |
# DELETE /users/1.json | |
def destroy | |
@user.destroy if @user | |
head :no_content | |
end | |
def login | |
if params[:username] && params[:password] | |
# login by username | |
user = User.find_by(username: params[:username]) | |
if user | |
if BCrypt::Password.new(user.password_digest) == params[:password] | |
payload = { | |
'user_id' => user.id, | |
'token_type' => 'client_a2', | |
'exp' => 4.hours.from_now.to_i, | |
} | |
token = jwt_encode(payload) | |
render json: { token: token }, status: 200 | |
else | |
render json: { error: "Usuário/Email ou senha incorretos, por favor tente novamente mais tarde."}, status: :unauthorized | |
end | |
else | |
#login by email | |
user = User.find_by(email: params[:username]) | |
if user | |
if BCrypt::Password.new(user.password_digest) == params[:password] | |
payload = { | |
'user_id' => user.id, | |
'token_type' => 'client_a2', | |
'exp' => 4.hours.from_now.to_i, | |
} | |
token = jwt_encode(payload) | |
render json: { token: token }, status: 200 | |
else | |
render json: { error: "Usuário/Email ou senha incorretos, por favor tente novamente mais tarde."}, status: :unauthorized | |
end | |
else | |
render json: { error: "Usuário/Email ou senha incorretos, por favor tente novamente mais tarde."}, status: :unauthorized | |
end | |
end | |
else | |
render json: { error: "Por favor preencha os campos corretamente."}, status: :unauthorized | |
end | |
end | |
def recovery_password | |
if params[:email] | |
user = User.find_by(email: params[:email]) | |
if user | |
payload = { | |
'user_id' => user.id, | |
'token_type' => 'client_a2', | |
'request_type' => 'password_recovery', | |
'exp' => 30.minutes.from_now.to_i, | |
} | |
token = jwt_encode(payload) | |
UsersMailer.recovery_password(user, token).deliver_later | |
render json: { success: 'Enviamos um email com o link para a alteração da senha da sua conta, favor verificar sua caixa de entrada.' }, status: 200 | |
else | |
render json: { error: "O email informado não está cadastrado no nosso sistema." }, status: :unauthorized | |
end | |
else | |
render json: { error: "Por favor preencha o campo de email corretamente." }, status: :unauthorized | |
end | |
end | |
private | |
def set_user | |
@user = User.find_by(id: params[:id]) | |
end | |
def user_params | |
params.require(:user).permit(:name, :username, :email, :password, :password_confirmation, :avatar, :bday, :gender, :rule_id) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Awesome! Thanks 👍