Skip to content

Instantly share code, notes, and snippets.

@bradleybuda
Created January 22, 2014 23:18
Show Gist options
  • Save bradleybuda/8569479 to your computer and use it in GitHub Desktop.
Save bradleybuda/8569479 to your computer and use it in GitHub Desktop.
class AccountRequestApprovalToken < ActiveRecord::Base
belongs_to :user
belongs_to :account_request
validates_presence_of :user_id, :account_request_id
validates_uniqueness_of :value
validates_uniqueness_of :account_request_id, scope: :user_id
before_create :assign_token_value
def assign_token_value
self.value = SecureRandom.hex
end
def to_param
# Use self#value to build URLs (instead of self#id)
value
end
def consumed?
consumed_at.present?
end
def consume!
ActiveRecord::Base.transaction do
req = self.account_request
author = self.user
raise if author.disabled? || !author.admin?
req.approve_by!(author)
self.consumed_at = Time.now
self.save!
end
end
end
class AccountRequestApprovalTokensController < ApplicationController
skip_before_filter :authenticate_user!
def consume
@token = AccountRequestApprovalToken.find_by_value params[:id]
if @token.consumed?
head :bad_request
else
@token.consume!
head :ok
end
end
end
class CreateAccountRequestApprovalTokens < ActiveRecord::Migration
def change
create_table :account_request_approval_tokens do |t|
t.integer :user_id, null: false
t.integer :account_request_id, null: false
t.string :value, null: false
t.datetime :consumed_at
end
add_index :account_request_approval_tokens, :value, unique: true
add_index :account_request_approval_tokens, [:user_id, :account_request_id], name: :index_account_request_approval_tokens_on_relations, unique: true
end
end
module EmailActionsHelper
def confirm_action(options)
helper_data = {
"@context" => "http://schema.org",
"@type" => "EmailMessage",
"action" => {
"@type" => "ConfirmAction",
"name" => options[:name],
"handler" => {
"@type" => "HttpActionHandler",
"url" => options[:url],
},
},
}
content_tag :script, type: 'application/ld+json' do
helper_data.to_json.html_safe
end
end
end
%html
%body
- if content_for? :email_action
= yield :email_action
%div(style="some style goes here")
= yield
- content_for :email_action do
- approve_url = consume_account_request_approval_token_url(@token)
= confirm_action name: 'Approve Request', url: approve_url
require 'digest/sha1'
# Use this code at your peril - it may not be as secure as issuing a random token
class SignatureBasedApprovalTokenController < ApplicationController
skip_before_filter :authenticate_user!
# URL looks like /users/:user_id/account_requests/:account_request_id/approve?signature=:signature
def consume
author = User.find params[:user_id]
request = AccountRequest.find params[:account_request_id]
expected_signature = Digest::SHA1.hexdigest "#{author.secret_approval_token}:#{request.secret_approval_token}"
if expected_signature == params[:signature]
request.approve_by!(author)
head :ok
else
head :forbidden
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment