Skip to content

Commit

Permalink
Merge pull request #54 from npauzenga/tasks/encryptor-model
Browse files Browse the repository at this point in the history
Tasks/encryptor-model + CreatePasswordReset Token Interactor
  • Loading branch information
npauzenga committed Jan 11, 2016
2 parents fc37fa2 + 9c4ada7 commit 8ebec8a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 7 deletions.
13 changes: 10 additions & 3 deletions app/interactors/create_password_reset_token.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
class CreatePasswordResetToken
include Interactor
class CreatePasswordResetToken < StandardInteraction
def validate_input
context.fail!(errors: "invalid input") unless context.user
end

def execute
context.user.update(reset_digest: Encryptor.generate_token[0])
end

def call
def validate_output
context.fail!(errors: "server error") unless context.user.reset_digest
end
end
19 changes: 19 additions & 0 deletions app/models/encryptor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Encryptor
include BCrypt

TOKEN_KEY = Rails.application.secrets.secret_key_base
TOKEN_HASH = "SHA512"

def self.digest_token(token)
OpenSSL::HMAC.hexdigest(TOKEN_HASH, TOKEN_KEY, token).to_s
end

def self.generate_token
raw = SecureRandom.urlsafe_base64.to_s
[digest_token(raw), raw]
end

def self.tokens_match?(raw_token, enc_token)
Encryptor.digest_token(raw_token) == enc_token
end
end
20 changes: 16 additions & 4 deletions spec/interactors/create_password_reset_token_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@
end

it "sets the reset digest" do
expect { subject }.to change(subject.user.reset_digest)
expect { subject }.to change { user.reset_digest }
end

it "sets the reset digest to a string" do
expect(subject.user.reset_digest).to be_a(String)
end
end

context "when input is invalid" do
context "when user is not valid" do
subject { described_class.call(user: nil) }

it "fails" do
is_expected.to be_a_failure
end
Expand All @@ -24,13 +30,19 @@
end
end

context "when output is invalid" do
context "when update fails" do
subject { described_class.call(user: user) }

before do
allow(user).to receive(:update).and_return(false)
end

it "fails" do
is_expected.to be_a_failure
end

it "adds an error to errors" do
expect(subject.errors).to eq("internal server error")
expect(subject.errors).to eq("server error")
end
end
end
Expand Down
56 changes: 56 additions & 0 deletions spec/models/encryptor_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require "rails_helper"
include BCrypt

RSpec.describe Encryptor do
context "methods" do
describe "self.digest_token" do
subject do
described_class.digest_token("test")
end

it "returns a string" do
is_expected.to be_a(String)
end
end

describe "self.generate_token" do
subject do
described_class.generate_token
end

it "returns a raw and a hashed token" do
is_expected.to be_an(Array)
end

it "sets the hashed token correctly" do
enc, raw = described_class.generate_token
expect(described_class.digest_token(raw)).to eq(enc)
end
end

describe "self.tokens_match?" do
context "when successful" do
subject do
enc, raw = described_class.generate_token
described_class.tokens_match?(raw, enc)
end

it "returns true when the tokens match" do
is_expected.to be_truthy
end
end

context "when unsuccessful" do
subject do
raw = described_class.generate_token
enc = "nope"
described_class.tokens_match?(raw[0], enc)
end

it "returns false when the tokens don't match" do
is_expected.to be_falsey
end
end
end
end
end

0 comments on commit 8ebec8a

Please sign in to comment.