Skip to content

Commit

Permalink
Implemented dashboard and rpc controller
Browse files Browse the repository at this point in the history
  • Loading branch information
luccastera committed Feb 7, 2024
1 parent e3b906d commit 842ed1f
Show file tree
Hide file tree
Showing 18 changed files with 386 additions and 51 deletions.
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,6 @@ group :development do
gem 'annotate'
end

gem "discard"
gem "discard"

gem "jwt"
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ GEM
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jwt (2.7.1)
launchy (2.5.2)
addressable (~> 2.8)
letter_opener (1.8.1)
Expand Down Expand Up @@ -312,6 +313,7 @@ DEPENDENCIES
faker
importmap-rails
jbuilder
jwt
letter_opener
pg (~> 1.1)
puma (>= 5.0)
Expand Down
57 changes: 56 additions & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,62 @@ class ApplicationController < ActionController::Base
def render_404
respond_to do |format|
format.html { render file: "#{Rails.root}/public/404.html", status: :not_found }
format.json { render json: { error: "Not found" }, status: :not_found }
format.json { render json: json_rpc_error(404, "Not Found"), status: :not_found }
end
end

def render_400
respond_to do |format|
format.html { render file: "#{Rails.root}/public/400.html", status: :bad_request }
format.json { render json: json_rpc_error(400, "Bad Request"), status: :bad_request }
end
end

def render_401
respond_to do |format|
format.html { render file: "#{Rails.root}/public/401.html", status: :unauthorized }
format.json { render json: json_rpc_error(401, "Unauthorized"), status: :unauthorized }
end
end

def validate_presence_of_jwt_token!
render_400 and return unless params['jwt'].present?
end

def authenticate_via_jwt! # rubocop:disable Metrics/AbcSize
if session[:account_quicknode_id].present?
@current_acccount = Account.kept.find_by(quicknode_id: session[:account_quicknode_id])
else
token = params['jwt']
begin
decoded_tokens = JWT.decode token, Rails.application.credentials.jwt.secret, true
@decoded_token = decoded_tokens.first
logger.info "[DASH] decoded_token: #{@decoded_token}"
session[:account_quicknode_id] = @decoded_token["quicknode_id"]
session[:email] = @decoded_token["email"]
session[:name] = @decoded_token["name"]
session[:organization_name] = @decoded_token["organization_name"]
rescue JWT::VerificationError, JWT::DecodeError => e
logger.error "[BAD JWT] #{e.message}"
@error = 'forged or missing JWT'
end
return if @error.present?

@current_acccount = Account.kept.find_by(quicknode_id: session[:account_quicknode_id])
@error = "account not provisioned" unless @current_acccount
end
end

private

def json_rpc_error(code, message)
{
id: 1,
error: {
code:,
message:,
},
jsonrpc: "2.0",
}
end
end
12 changes: 9 additions & 3 deletions app/controllers/dashboard_controller.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# frozen_string_literal: true

class DashboardController < ApplicationController
def show
respond_to do |format|
format.html
before_action :validate_presence_of_jwt_token!
before_action :authenticate_via_jwt!

def index
unless @current_acccount
logger.info "[401 Unauthorized] #{@error}"
render_401 and return
end

@endpoint = @current_acccount.endpoints.kept
end
end
18 changes: 9 additions & 9 deletions app/controllers/provisioning_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
class ProvisioningController < ApplicationController
skip_before_action :verify_authenticity_token

before_action :set_account_and_endpoint, only: %i[update deactivate_endpoint deprovision]

# Authenticate with HTTP Basic Auth.
# To find the credentials: run bin/rails credentials:edit
http_basic_authenticate_with(
Expand Down Expand Up @@ -34,10 +36,7 @@ def provision
end

def update
@account = Account.find_by(quicknode_id: params["quicknode-id"])
render_404 and return unless @account

@endpoint = Endpoint.find_by(quicknode_id: params["endpoint-id"])
render_404 and return unless @endpoint

@account.update(
Expand All @@ -59,10 +58,7 @@ def update
end

def deactivate_endpoint
@account = Account.find_by(quicknode_id: params["quicknode-id"])
render_404 and return unless @account

@endpoint = Endpoint.find_by(quicknode_id: params["endpoint-id"])
render_404 and return unless @endpoint

@endpoint.discard
Expand All @@ -73,10 +69,7 @@ def deactivate_endpoint
end

def deprovision
@account = Account.find_by(quicknode_id: params["quicknode-id"])
render_404 and return unless @account

@endpoint = Endpoint.find_by(quicknode_id: params["endpoint-id"])
render_404 and return unless @endpoint

@account.endpoints.each(&:discard)
Expand All @@ -86,4 +79,11 @@ def deprovision
status: "success",
}
end

private

def set_account_and_endpoint
@account = Account.kept.find_by(quicknode_id: params["quicknode-id"])
@endpoint = Endpoint.kept.find_by(quicknode_id: params["endpoint-id"])
end
end
22 changes: 21 additions & 1 deletion app/controllers/rpc_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# frozen_string_literal: true

class RPCController < ApplicationController
def rpc; end
before_action :validate_headers

RPC_METHODS = %w[qn_hello_world].freeze

def rpc
@account = Account.kept.find_by(quicknode_id: request.headers["X-QUICKNODE-ID"])
render_404 and return unless @account.present?

render_404 and return unless RPC_METHODS.include?(params[:method])

render json: { jsonrpc: "2.0", result: "hello world" }
end

private

def validate_headers # rubocop:disable Metrics/CyclomaticComplexity
render_400 and return unless request.headers["X-QUICKNODE-ID"].present?
render_400 and return unless request.headers["X-INSTANCE-ID"].present?
render_400 and return unless request.headers["X-QN-CHAIN"].present?
render_400 and return unless request.headers["X-QN-NETWORK"].present?
end
end
5 changes: 5 additions & 0 deletions app/views/dashboard/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<h1>Dashboard</h1>

<%= session[:name] %>
<%= session[:email] %>
<%= session[:organization_name] %>
2 changes: 0 additions & 2 deletions app/views/dashboard/show.html.erb

This file was deleted.

2 changes: 1 addition & 1 deletion config/credentials.yml.enc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
aTPehLiCrSJ0I7BwkJ6q/zX+M+lg34DcaNO4qvWUtg7hKDnGxIwo3xwCnHWWobKmoISPBVAm1v8amIQxUBi7+Sb2uIXcb8OoO9HwULDW6LBDvXrjncbDS4J2tmHUlkCFr+ENQpMPjOth9msJYmUm7MgWM0TLowNSFD7oVS0QdDXMkrvmjKVDpVjAQziLUCEZmbWTiDkhSgAgjxvxDbHxk+7XIkKiQVTepindc6e3cXOviVB7O49f/p/cHaIwsEkjxD7XpHGNa8bDdbSPqQf7JFbP+Yi5AwE+wu7Sw3oWTd4bWOtEYm/8AEBBmjYieeh+PPPsnXwrRVtTGAHp/CPi6VfvJhU1jNSODQXEmdtFt7avgQfjn1yjZ9c7nj8XmJXo66tycV56VjJMZ1SndiA=--Fxhv/oUs/THaAbR8--tbwfBVPso0I6FZHZb5K6IQ==
yiQVMZFkaATpdGSSl2kUoXV1hl8UQItLV2LawNnnlpvooJz9n2FasjKQSvO6xvmEgfy8DQ9Tt9WODHB+fCIMCqKY1kWS4cMVb6s3orYA3t08O7lNzGN0p3iPlI564m1ITu7jJ/k31SLmJAiRdfelLsgjhP6BrTaFUuqnyxuKkd4QVsZc0cVQfu5QvMyoKrIfTyY/lMvjtj6pcI+5laerCsI1U3AQuadTuXx1/Csz2fqLnWITEPz0b6X8SoPWvEoHAvVyT+u6Qf/Wm6VmSKqu5oRqota0MqBoyx5vMQsIQ/y5UChn3pCz5XnwZOdSYxj36PpzyZ6PGvgf9AGhsCDA7BtcADd8Ia6bWkwFSTaNWnCk1XzE5eCvC5O705N9EyOJtxJdmd656H5QV+MNkmv1jQ8iLLIgqKddj/KWwhzmawP3IDq7fJalpzk=--tVJ/MS2Xvc39LbvV--LAAV2BfvBCnFIsPfb4Ztbg==
19 changes: 11 additions & 8 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@
root "pages#index"

# Dashboard
get 'dashboard/:quicknode_id' => 'dashboard#show', as: 'dashboard'
get 'dashboard' => 'dashboard#index', as: 'dashboard'

# Provisioning
post 'provision' => "provisioning#provision", as: 'provision'
put 'update' => "provisioning#update", as: 'update'
delete 'deactivate_endpoint' => "provisioning#deactivate_endpoint", as: 'deactivate_endpoint'
delete 'deprovision' => "provisioning#deprovision", as: 'deprovision'
# The methods below are APIs that should only use JSON format
defaults format: :json do
# Provisioning
post 'provision' => "provisioning#provision", as: 'provision'
put 'update' => "provisioning#update", as: 'update'
delete 'deactivate_endpoint' => "provisioning#deactivate_endpoint", as: 'deactivate_endpoint'
delete 'deprovision' => "provisioning#deprovision", as: 'deprovision'

# RPC
post 'rpc' => "rpc#rpc", as: 'rpc'
# RPC
post 'rpc' => "rpc#rpc", as: 'rpc'
end

end
66 changes: 66 additions & 0 deletions public/400.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>Bad Request (400)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
.rails-default-error-page {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}

.rails-default-error-page div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}

.rails-default-error-page div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}

.rails-default-error-page h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}

.rails-default-error-page div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>

<body class="rails-default-error-page">
<!-- This file lives in public/400.html -->
<div class="dialog">
<div>
<h1>Bad Request</h1>
<p>The request is not valid.</p>
</div>
</div>
</body>
</html>
65 changes: 65 additions & 0 deletions public/401.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<title>Unauthorized (401)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
.rails-default-error-page {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}

.rails-default-error-page div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}

.rails-default-error-page div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}

.rails-default-error-page h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}

.rails-default-error-page div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>

<body class="rails-default-error-page">
<!-- This file lives in public/500.html -->
<div class="dialog">
<div>
<h1>Unauthorized.</h1>
</div>
</div>
</body>
</html>
1 change: 0 additions & 1 deletion spec/helpers/dashboard_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@
# end
# end
RSpec.describe DashboardHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
1 change: 0 additions & 1 deletion spec/helpers/pages_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@
# end
# end
RSpec.describe PagesHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
1 change: 0 additions & 1 deletion spec/helpers/provisioning_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,4 @@
# end
# end
RSpec.describe ProvisioningHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
1 change: 0 additions & 1 deletion spec/helpers/rpc_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@
# end
# end
RSpec.describe RPCHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading

0 comments on commit 842ed1f

Please sign in to comment.