stricter JSON validation

pull/1207/head
Rick Carlino 2019-05-22 15:19:26 -05:00
parent ed24e82c81
commit bf69ae09bd
26 changed files with 177 additions and 186 deletions

View File

@ -16,6 +16,7 @@ module Api
NOT_FBOS = Gem::Version.new("999.999.999")
respond_to :json
before_action :raw_json, only: [:update, :create]
before_action :check_fbos_version
before_action :set_default_stuff
before_action :authenticate_user!
@ -41,8 +42,10 @@ module Api
sorry "You can't perform that action. #{exc.message}", 403
end
ONLY_JSON = "This is a JSON API. Please use _valid_ JSON. " \
"Validate JSON objects at https://jsonlint.com/"
rescue_from OnlyJson do |e|
sorry "This is a JSON API. Please use _valid_ JSON.", 422
sorry ONLY_JSON, 422
end
rescue_from Errors::NoBot do |exc|
@ -80,17 +83,14 @@ module Api
# Our API does not do things the "Rails way" (we use Mutations for input
# sanitation) so we can ignore this and grab the raw input.
def raw_json
@raw_json ||= JSON.parse(request.body.read).tap { |x| symbolize(x) }
@raw_json ||= parse_json
rescue JSON::ParserError
raise OnlyJson
end
# PROBLEM: We want to deep_symbolize_keys! on all JSON inputs, but what if
# the user POSTs an Array? It will crash because [] does not respond_to
# deep_symbolize_keys! This is the workaround. I could probably use a
# refinement.
def symbolize(x)
x.is_a?(Array) ? x.map(&:deep_symbolize_keys!) : x.deep_symbolize_keys!
def parse_json
body = request.body.read
body.present? ? JSON.parse(body, symbolize_names: true) : nil
end
REQ_ID = "X-Farmbot-Rpc-Id"

View File

@ -12,12 +12,12 @@ module Api
# POST /api/device
def create
mutate Devices::Create.run(params.as_json, user: current_user)
mutate Devices::Create.run(raw_json, user: current_user)
end
# PATCH/PUT /api/device
def update
mutate Devices::Update.run(params.as_json, device: current_device)
mutate Devices::Update.run(raw_json, device: current_device)
end
# DELETE /api/devices/1
@ -35,11 +35,11 @@ module Api
end
def seed
mutate Devices::CreateSeedData.run params.as_json, device: current_device
mutate Devices::CreateSeedData.run raw_json, device: current_device
end
def reset
mutate Devices::Reset.run(params.as_json, device: current_device)
mutate Devices::Reset.run(raw_json, device: current_device)
end
private

View File

@ -3,14 +3,15 @@ module Api
skip_before_action :authenticate_user!, only: [:create, :update]
def create
mutate PasswordResets::Create.run(email: params[:email])
mutate PasswordResets::Create.run(email: raw_json[:email])
end
def update
mutate PasswordResets::Update.run(
password: params[:password],
password_confirmation: params[:password_confirmation],
token: params[:id])
password: raw_json[:password],
password_confirmation: raw_json[:password_confirmation],
token: raw_json[:id],
)
end
end
end

View File

@ -19,13 +19,13 @@ module Api
end
def snapshot
mutate SavedGardens::Snapshot.run(params.as_json, device: current_device)
mutate SavedGardens::Snapshot.run(device: current_device)
end
def apply
params = { garden: garden,
device: current_device,
destructive: (request.method == "POST") }
params = { garden: garden,
device: current_device,
destructive: (request.method == "POST") }
mutate SavedGardens::Apply.run(params)
end

View File

@ -48,7 +48,7 @@ module Api
end
def if_properly_formatted
user = params.as_json.deep_symbolize_keys.fetch(:user, {})
user = raw_json.fetch(:user, {})
# If data handling for this method gets any more complicated,
# extract into a mutation.
if(user.is_a?(Hash))

View File

@ -22,27 +22,27 @@ module Api
def resend_verification
mutate Users::ResendVerification
.run(user: User.find_by!(email: params[:email]))
.run(user: User.find_by!(email: raw_json[:email]))
end
def control_certificate
binding.pry unless raw_json.is_a?(Hash)
mutate Users::GenerateControlCert.run(raw_json, device: current_device)
end
private
def user_params
user = params
.as_json
.merge!(params.as_json["user"] || {})
user = raw_json
.merge!(raw_json[:user] || {})
.deep_symbolize_keys
{email: user[:email],
name: user[:name],
password: user[:password],
password_confirmation: user[:password_confirmation],
new_password: user[:new_password],
{ email: user[:email],
name: user[:name],
password: user[:password],
password_confirmation: user[:password_confirmation],
new_password: user[:new_password],
new_password_confirmation: user[:new_password_confirmation],
agree_to_terms: user[:agree_to_terms]}
agree_to_terms: user[:agree_to_terms] }
end
end
end

View File

@ -3,7 +3,7 @@
module Api
class WebcamFeedsController < Api::AbstractController
def create
mutate WebcamFeeds::Create.run(params.as_json, device: current_device)
mutate WebcamFeeds::Create.run(raw_json, device: current_device)
end
def index
@ -15,14 +15,14 @@ module Api
end
def update
mutate WebcamFeeds::Update.run(params.as_json, webcam_feed: webcam)
mutate WebcamFeeds::Update.run(raw_json, webcam_feed: webcam)
end
def destroy
render json: webcam.destroy! && ""
end
private
private
def webcam
webcams.find(params[:id])

View File

@ -15,7 +15,7 @@ module Auth
def validate
cipher_text = Base64.decode64(credentials)
plain_text = PRIVATE_KEY.private_decrypt(cipher_text)
cred_info = JSON.parse(plain_text).symbolize_keys!
cred_info = JSON.parse(plain_text, symbolize_names: true)
User.try_auth(cred_info[:email], cred_info[:password]) do |maybe_user|
whoops! unless maybe_user
@user = maybe_user

View File

@ -44,7 +44,7 @@ if Rails.env == "development"
u = User.last
u.update_attributes(device: Devices::Create.run!(user: u))
# === Parameterized Sequence stuff
json = JSON.parse(File.read("spec/lib/celery_script/ast_fixture5.json")).deep_symbolize_keys
json = JSON.parse(File.read("spec/lib/celery_script/ast_fixture5.json"), symbolize_names: true)
Sequences::Create.run!(json, device: u.device)
# === Parameterized Sequence stuff
Log.transaction do

View File

@ -10,7 +10,7 @@ describe Api::DevicesController do
it "creates a new device for a user" do
sign_in user
params = { user_id: user.id, name: Faker::Food.vegetables }
post :create, params: params
post :create, body: params.to_json
expect(response.status).to eq(200)
resp = JSON.parse(response.body)
new_device = Device.find(resp["id"])
@ -22,7 +22,7 @@ describe Api::DevicesController do
it "defaults name to `FarmBot`" do
sign_in user
params = { user_id: user.id }
post :create, params: params
post :create, body: params.to_json
expect(response.status).to eq(200)
expect(json.fetch(:name)).to eq("FarmBot")
end

View File

@ -24,7 +24,7 @@ describe Api::DevicesController do
device.update_attributes(name: "#{SecureRandom.hex(10)}")
run_jobs_now { post :reset, params: { password: password } }
run_jobs_now { post :reset, body: { password: password }.to_json }
resources
.without("token_issuance")
@ -44,7 +44,7 @@ describe Api::DevicesController do
sign_in user
device = user.device
run_jobs_now { post :reset, params: {} }
run_jobs_now { post :reset, body: {}.to_json }
expect(response.status).to eq(422)
expect(json.fetch(:password)).to eq("Password is required")
end

View File

@ -183,7 +183,7 @@ describe Api::DevicesController do
old_name = device.name
expect(device.plants.count).to eq(0)
run_jobs_now do
post :seed, params: { product_line: "none" }
post :seed, body: { product_line: "none" }.to_json
end
expect(response.status).to eq(200)
expect(device.plants.count).to eq(0)
@ -192,7 +192,9 @@ describe Api::DevicesController do
def start_tests(product_line)
sign_in user
run_jobs_now { post :seed, params: { product_line: product_line } }
run_jobs_now do
post :seed, body: { product_line: product_line }.to_json
end
expect(response.status).to eq(200)
device.reload
end

View File

@ -5,17 +5,16 @@ require "spec_helper"
describe Api::DevicesController do
include Devise::Test::ControllerHelpers
describe "#update" do
let(:user) { FactoryBot.create(:user) }
let(:user2) { FactoryBot.create(:user) }
let(:user) { FactoryBot.create(:user) }
let(:user2) { FactoryBot.create(:user) }
let(:device) { user.device }
let(:tool) { FactoryBot.create(:tool, device: user.device) }
let(:tool) { FactoryBot.create(:tool, device: user.device) }
it "updates a Device" do
sign_in user
fake_name = Faker::Name.name
put :update,
params: {id: user.device.id, name: fake_name},
body: { id: user.device.id, name: fake_name }.to_json,
session: { format: :json }
# put path, params, options
user.reload
@ -28,7 +27,7 @@ describe Api::DevicesController do
sign_in user
before = user.device.timezone
put :update,
params: {id: user.device.id, timezone: "NO!"},
body: { id: user.device.id, timezone: "NO!" }.to_json,
session: { format: :json }
# put path, params, options
user.reload
@ -41,7 +40,7 @@ describe Api::DevicesController do
it "updates a Device timezone correctly" do
sign_in user
fake_tz = Device::TIMEZONES.sample
put :update, params: {id: user.device.id, timezone: fake_tz}, session: { format: :json }
put :update, body: { id: user.device.id, timezone: fake_tz }.to_json, session: { format: :json }
user.reload
device = user.reload.device.reload
expect(device.timezone).to eq(fake_tz)
@ -51,10 +50,10 @@ describe Api::DevicesController do
it "mounts a tool" do
sign_in user
put :update,
params: {
body: {
id: user.device.id,
mounted_tool_id: tool.id
},
mounted_tool_id: tool.id,
}.to_json,
session: { format: :json }
user.reload
device = user.reload.device.reload
@ -65,10 +64,10 @@ describe Api::DevicesController do
it "performs referential integrity checks on mounted_tool_id" do
sign_in user
put :update,
params: {
body: {
id: user.device.id,
mounted_tool_id: (FactoryBot.create(:tool).id + 1)
},
mounted_tool_id: (FactoryBot.create(:tool).id + 1),
}.to_json,
session: { format: :json }
expect(response.status).to eq(422)
expect(json[:mounted_tool_id]).to include("Can't mount to tool")
@ -79,10 +78,10 @@ describe Api::DevicesController do
device.update_attributes!(mounted_tool_id: tool.id)
expect(device.mounted_tool_id).to be
put :update,
params: { id: user.device.id, mounted_tool_id: 0 },
body: { id: user.device.id, mounted_tool_id: 0 }.to_json,
session: { format: :json }
expect(device.reload.mounted_tool_id).not_to be
expect(json[:mounted_tool_id]).to be(nil)
expect(device.reload.mounted_tool_id).not_to be
expect(json[:mounted_tool_id]).to be(nil)
end
end
end

View File

@ -1,16 +1,16 @@
require 'spec_helper'
require "spec_helper"
describe Api::PasswordResetsController do
include Devise::Test::ControllerHelpers
describe '#create' do
describe "#create" do
let(:user) { FactoryBot.create(:user) }
it 'resets password for a user' do
it "resets password for a user" do
params = { email: user.email }
old_email_count = ActionMailer::Base.deliveries.length
run_jobs_now do
post :create, params: params
post :create, body: params.to_json
expect(response.status).to eq(200)
expect(ActionMailer::Base.deliveries.length).to be > old_email_count
message = last_email.to_s
@ -18,53 +18,53 @@ describe Api::PasswordResetsController do
end
end
it 'resets password using a reset token' do
params = {password: "xpassword123",
it "resets password using a reset token" do
params = { password: "xpassword123",
password_confirmation: "xpassword123",
fbos_version: Gem::Version.new("999.9.9"),
id: PasswordResetToken
.issue_to(user)
.encoded }
put :update, params: params
fbos_version: Gem::Version.new("999.9.9"),
id: PasswordResetToken
.issue_to(user)
.encoded }
put :update, body: params.to_json, format: :json
expect(user
.reload
.valid_password?(params[:password])).to eq(true)
.reload
.valid_password?(params[:password])).to eq(true)
expect(response.status).to eq(200)
expect(json.keys).to include(:token)
expect(json.keys).to include(:user)
end
it 'disallows short passwords' do
params = {password: "xpass",
it "disallows short passwords" do
params = { password: "xpass",
password_confirmation: "xpass",
fbos_version: Gem::Version.new("999.9.9"),
id: PasswordResetToken
.issue_to(user)
.encoded }
put :update, params: params
fbos_version: Gem::Version.new("999.9.9"),
id: PasswordResetToken
.issue_to(user)
.encoded }
put :update, body: params.to_json, format: :json
expect(user
.reload
.valid_password?(params[:password])).to eq(false)
.reload
.valid_password?(params[:password])).to eq(false)
expect(response.status).to eq(422)
expect(json[:password]).to include("too short")
end
it 'handles token expiration' do
token = PasswordResetToken
.issue_to(user, {exp: Time.now.yesterday})
.encoded
it "handles token expiration" do
token = PasswordResetToken
.issue_to(user, { exp: Time.now.yesterday })
.encoded
params = { password: "xpassword123",
params = { password: "xpassword123",
password_confirmation: "xpassword123",
id: token }
id: token }
put :update, params: params
put :update, body: params.to_json, format: :json
expect(response.status).to eq(422)
expect(user.reload.valid_password?(params[:password])).to eq(false)
expect(json.to_json).to include(PasswordResets::Update::OLD_TOKEN)
end
it 'handles bad emails' do
it "handles bad emails" do
result = PasswordResets::Create.run(email: "bad@wrong.com")
expect(result.errors["email"].message).to eq("Email not found")
end

View File

@ -1,12 +1,12 @@
require 'spec_helper'
require "spec_helper"
describe Api::PeripheralsController do
include Devise::Test::ControllerHelpers
describe '#create' do
describe "#create" do
let(:user) { FactoryBot.create(:user) }
it 'makes a Peripheral' do
it "makes a Peripheral" do
sign_in user
before = Peripheral.count
post :create,
@ -18,12 +18,12 @@ describe Api::PeripheralsController do
expect(before < Peripheral.count).to be_truthy
end
it 'requires logged in user' do
post :create, params: { pin: 13, label: "LED" }
it "requires logged in user" do
post :create, body: { pin: 13, label: "LED" }.to_json
expect(response.status).to eq(401)
end
it 'limits label length' do
it "limits label length" do
sign_in user
before = Peripheral.count
post :create,

View File

@ -10,7 +10,7 @@ describe Api::RegimensController do
it "kicks back missing parameters" do
sign_in user
celery = File.read("spec/lib/celery_script/ast_fixture5.json")
json = JSON.parse(celery).deep_symbolize_keys
json = JSON.parse(celery, symbolize_names: true)
s = Sequences::Create.run!(json, device: user.device)
# No paramaters here.

View File

@ -3,11 +3,10 @@ require "spec_helper"
describe Api::SavedGardensController do
include Devise::Test::ControllerHelpers
let(:user) { FactoryBot.create(:user) }
let(:user) { FactoryBot.create(:user) }
let(:saved_gardens) { FactoryBot.create_list(:saved_garden, 3, device: user.device) }
describe "#index" do
it "shows all saved_gardens" do
sign_in user
garden_size = saved_gardens.length
@ -23,7 +22,7 @@ describe Api::SavedGardensController do
sign_in user
b4 = user.device.saved_gardens.count
params = { name: Faker::Food.vegetables }
post :create, params: {format: :json}, body: params.to_json
post :create, params: { format: :json }, body: params.to_json
expect(response.status).to eq(200)
expect(json[:name]).to be_kind_of(String)
expect(json[:name]).to eq(params[:name])
@ -35,7 +34,7 @@ describe Api::SavedGardensController do
it "updates attributes" do
sign_in user
garden = saved_gardens.first
b4 = garden.name
b4 = garden.name
params = { name: Faker::Food.vegetables }
put :update, params: { format: :json, id: garden.id }, body: params.to_json
expect(response.status).to eq(200)
@ -48,7 +47,7 @@ describe Api::SavedGardensController do
it "destroys saved_gardens" do
sign_in user
garden = saved_gardens.first
b4 = saved_gardens.length
b4 = saved_gardens.length
delete :destroy, params: { id: garden.id }
expect(response.status).to eq(200)
expect(user.device.saved_gardens.count).to be < b4
@ -60,7 +59,7 @@ describe Api::SavedGardensController do
SavedGarden.destroy_all
PlantTemplate.destroy_all
sign_in user
gardens_b4 = user.device.saved_gardens.count
gardens_b4 = user.device.saved_gardens.count
templates_b4 = user.device.plant_templates.count
plants = FactoryBot.create_list(:plant, 3, device: user.device)
post :snapshot
@ -81,7 +80,7 @@ describe Api::SavedGardensController do
saved_garden = FactoryBot.create(:saved_garden, device: user.device)
FactoryBot.create_list(:plant_template, 3, device: user.device, saved_garden: saved_garden)
old_plant_count = user.device.plants.count
patch :apply, params: {id: saved_garden.id }
patch :apply, params: { id: saved_garden.id }
expect(response.status).to eq(200)
expect(user.device.plants.count).to be > old_plant_count
end
@ -96,25 +95,22 @@ describe Api::SavedGardensController do
saved_garden: saved_garden)
plant = FactoryBot.create(:plant, device: user.device)
FakeSequence.create(device: user.device,
body: [{ kind: "move_absolute",
args: {
location: {
kind: "point",
args: { pointer_type: "Plant", pointer_id: plant.id }
},
speed: 100,
offset: { kind: "coordinate", args: { x: 0, y: 0, z: 0 } }
}
}])
body: [{ kind: "move_absolute",
args: {
location: {
kind: "point",
args: { pointer_type: "Plant", pointer_id: plant.id },
},
speed: 100,
offset: { kind: "coordinate", args: { x: 0, y: 0, z: 0 } },
} }])
old_plant_count = user.device.plants.count
post :apply, params: {id: saved_garden.id }
post :apply, params: { id: saved_garden.id }
expect(response.status).to be(422)
expect(user.device.plants.count).to eq(old_plant_count)
expect(json[:whoops])
.to include("Unable to remove the following plants from the garden")
expect(json[:whoops])
.to include("plant at (#{plant.x}, #{plant.y}, #{plant.z})")
expect(json[:whoops]).to include("Unable to remove the following plants from the garden")
expect(json[:whoops]).to include("plant at (#{plant.x}, #{plant.y}, #{plant.z})")
end
it "performs 'destructive' garden application" do
@ -123,10 +119,10 @@ describe Api::SavedGardensController do
PlantTemplate.destroy_all
sign_in user
saved_garden = FactoryBot.create(:saved_garden, device: user.device)
plant = FactoryBot.create(:plant, device: user.device)
plant = FactoryBot.create(:plant, device: user.device)
FactoryBot.create_list(:plant_template, 3, device: user.device, saved_garden: saved_garden)
old_plant_count = user.device.plants.count
post :apply, params: {id: saved_garden.id }
post :apply, params: { id: saved_garden.id }
expect(response.status).to eq(200)
expect(user.device.plants.count).to be > old_plant_count
expect(Plant.exists?(plant.id)).to be false

View File

@ -1,45 +1,45 @@
require 'spec_helper'
require "spec_helper"
describe Api::SensorReadingsController do
include Devise::Test::ControllerHelpers
describe 'CRUD actions' do
let(:user) { FactoryBot.create(:user) }
describe "CRUD actions" do
let(:user) { FactoryBot.create(:user) }
let (:reading) { FactoryBot.create(:sensor_reading, device: user.device) }
it 'makes a sensor reading' do
it "makes a sensor reading" do
sign_in user
before = SensorReading.count
post :create,
body: { pin: 13, value: 128, x: nil, y: 1, z: 2, mode: 1 }.to_json,
params: { format: :json }
expect(response.status).to eq(200)
expect(json[:id]).to be_kind_of(Integer)
expect(response.status).to eq(200)
expect(json[:id]).to be_kind_of(Integer)
expect(json[:created_at]).to be_kind_of(String)
expect(json[:value]).to eq(128)
expect(json[:device_id]).to eq(nil) # Use the serializer, not as_json.
expect(json[:x]).to eq(nil)
expect(json[:y]).to eq(1)
expect(json[:z]).to eq(2)
expect(json[:pin]).to eq(13)
expect(json[:mode]).to eq(1)
expect(json[:value]).to eq(128)
expect(json[:device_id]).to eq(nil) # Use the serializer, not as_json.
expect(json[:x]).to eq(nil)
expect(json[:y]).to eq(1)
expect(json[:z]).to eq(2)
expect(json[:pin]).to eq(13)
expect(json[:mode]).to eq(1)
expect(before < SensorReading.count).to be_truthy
end
it 'shows one reading' do
it "shows one reading" do
sign_in user
SensorReading.destroy_all
id = reading.id
get :show, params: { format: :json, id: id }
expect(json).to be_kind_of(Hash)
reading.reload
[ :id, :value, :x, :y, :z, :pin, :mode ].map do |attr|
[:id, :value, :x, :y, :z, :pin, :mode].map do |attr|
expect(json[attr]).to eq(reading.send(attr))
end
end
it 'shows all readings' do
it "shows all readings" do
sign_in user
SensorReading.destroy_all
id = reading.id
@ -47,11 +47,11 @@ describe Api::SensorReadingsController do
expect(json).to be_kind_of(Array)
expect(json.length).to eq(user.device.sensor_readings.length)
keys = json.first.keys
expect(json.map{|x| x[:id] }).to include(id)
expect(json.map { |x| x[:id] }).to include(id)
expect(keys).to include(:x, :y, :z, :value, :pin)
end
it 'destroys a reading' do
it "destroys a reading" do
sign_in user
SensorReading.destroy_all
id = reading.id
@ -62,8 +62,8 @@ describe Api::SensorReadingsController do
expect(before).to be > SensorReading.count
end
it 'requires logged in user' do
post :create, params: {}
it "requires logged in user" do
post :create, body: {}.to_json
expect(response.status).to eq(401)
end
end

View File

@ -8,7 +8,7 @@ describe Api::TokensController do
let(:user) { FactoryBot.create(:user, password: "password") }
it 'creates a new token' do
payload = {user: {email: user.email, password: "password"}}
post :create, params: payload
post :create, body: payload.to_json
token = json[:token][:unencoded]
expect(token[:iss].last).not_to eq("/") # Trailing slashes are BAD!
expect(token[:iss]).to include($API_URL)
@ -17,14 +17,14 @@ describe Api::TokensController do
it 'handles bad params' do
err_msg = Api::TokensController::NO_USER_ATTR
payload = {user: "NOPE!"}
post :create, params: payload
post :create, body: payload.to_json
expect(json[:error]).to include(err_msg)
end
it 'does not bump last_saw_api if it is not a bot' do
payload = {user: {email: user.email, password: "password"}}
before = user.device.last_saw_api
post :create, params: payload
post :create, body: payload.to_json
after = user.device.reload.last_saw_api
expect(before).to eq(after)
end
@ -35,7 +35,7 @@ describe Api::TokensController do
request.env["HTTP_USER_AGENT"] = ua
payload = {user: {email: user.email, password: "password"}}
before = user.device.last_saw_api || Time.now
post :create, params: payload
post :create, body: payload.to_json
after = user.device.reload.last_saw_api
expect(after).to be
expect(after).to be > before
@ -48,7 +48,7 @@ describe Api::TokensController do
payload = {user: {email: user.email, password: "password"}}
allow_any_instance_of(Api::TokensController)
.to receive(:xhr?).and_return(true)
post :create, params: payload
post :create, body: payload.to_json
expect(json.dig(:token, :unencoded, :aud)).to be
expect(json.dig(:token, :unencoded, :aud))
.to eq(AbstractJwtToken::HUMAN_AUD)
@ -56,7 +56,7 @@ describe Api::TokensController do
it "issues a '?' AUD to all others" do
payload = {user: {email: user.email, password: "password"}}
post :create, params: payload
post :create, body: payload.to_json
expect(json.dig(:token, :unencoded, :aud)).to be
expect(json.dig(:token, :unencoded, :aud))
.to eq(AbstractJwtToken::UNKNOWN_AUD)

View File

@ -26,7 +26,7 @@ describe Api::UsersController do
it "errors if you try to delete with the wrong password" do
sign_in user
delete :destroy, params: { password: "NOPE!" }, format: :json
delete :destroy, body: { password: "NOPE!" }.to_json, format: :json
expect(response.status).to eq(422)
expect(json[:password]).to eq(Users::Destroy::BAD_PASSWORD)
end
@ -34,7 +34,7 @@ describe Api::UsersController do
it "deletes a user account" do
sign_in user
run_jobs_now do
delete :destroy, params: { password: user.password }, format: :json
delete :destroy, body: { password: user.password }.to_json, format: :json
end
expect(response.status).to eq(200)
expect(User.where(id: user.id).count).to eq(0)
@ -48,7 +48,7 @@ describe Api::UsersController do
name: "Ricky McRickerson",
format: :json,
}
patch :update, params: input
patch :update, body: input.to_json
expect(response.status).to eq(200)
expect(json[:name]).to eq("Ricky McRickerson")
unless User::SKIP_EMAIL_VALIDATION
@ -73,7 +73,7 @@ describe Api::UsersController do
format: :json,
}
expect(TokenIssuance.where(device: user.device).count).to be >= 1
patch :update, params: input
patch :update, body: input.to_json
expect(response.status).to eq(200)
expect(TokenIssuance.where(device: user.device).count).to be <= 1
user.reload
@ -90,7 +90,7 @@ describe Api::UsersController do
password_confirmation: "123456789",
format: :json,
}
patch :update, params: input
patch :update, body: input.to_json
expect(response.status).to eq(422)
expect(json[:password]).to eq(Users::Update::PASSWORD_PROBLEMS)
end
@ -104,7 +104,7 @@ describe Api::UsersController do
password_confirmation: "123456789",
format: :json,
}
patch :update, params: input
patch :update, body: input.to_json
expect(response.status).to eq(422)
expect(json[:password]).to eq(Users::Update::PASSWORD_PROBLEMS)
end
@ -119,7 +119,7 @@ describe Api::UsersController do
name: "Frank" }
old_email_count = ActionMailer::Base.deliveries.length
run_jobs_now do
post :create, params: params
post :create, body: params.to_json
user = User.last
if User::SKIP_EMAIL_VALIDATION
puts BIG_WARNING
@ -151,7 +151,7 @@ describe Api::UsersController do
password: "Password321",
email: email,
name: "Frank" }
post :create, params: params
post :create, body: params.to_json
expect(User.count > original_count).to be_falsy
expect(json[:password]).to include("do not match")
expect(response.status).to eq(422)
@ -160,9 +160,9 @@ describe Api::UsersController do
it "generates a certificate to transfer device control" do
user1 = FactoryBot.create(:user, password: "password123")
user2 = FactoryBot.create(:user, password: "password456")
body = { email: user2.email, password: "password456" }.to_json
body = { email: user2.email, password: "password456" }
sign_in user1
post :control_certificate, body: body, format: :json
post :control_certificate, body: body.to_json, format: :json
expect(response.status).to eq(200)
credentials = response.body
expect(credentials).to be_kind_of(String)
@ -173,9 +173,9 @@ describe Api::UsersController do
it "prevents creating control certs for bad credentials" do
user1 = FactoryBot.create(:user, password: "password123")
body = { email: "wrong@wrong.com", password: "password456" }.to_json
body = { email: "wrong@wrong.com", password: "password456" }
sign_in user1
post :control_certificate, body: body, format: :json
post :control_certificate, body: body.to_json, format: :json
expect(response.status).to eq(422)
expect(json[:credentials]).to include("can't proceed")
end
@ -187,7 +187,7 @@ describe Api::UsersController do
confirmed_at: Time.now)
post :resend_verification,
params: { email: verified.email },
body: { email: verified.email }.to_json,
format: :json
expect(response.status).to eq(422)
@ -200,9 +200,8 @@ describe Api::UsersController do
password_confirmation: "password123")
post :resend_verification,
params: { email: unverified.email },
body: { email: unverified.email }.to_json,
format: :json
expect(response.status).to eq(200)
expect(json[:user]).to include(Users::ResendVerification::SENT)
end

View File

@ -8,7 +8,7 @@ describe Api::WebcamFeedsController do
sign_in user
input = { name: "name1", url: "url1" }
b4 = WebcamFeed.count
post :create, params: input
post :create, body: input.to_json
expect(response.status).to eq(200)
expect(WebcamFeed.count).to be > b4
expect(user.device.webcam_feeds.count).to eq(1)

View File

@ -1,18 +1,18 @@
require 'spec_helper'
require "spec_helper"
describe Api::WebcamFeedsController do
let(:user) { FactoryBot.create(:user) }
include Devise::Test::ControllerHelpers
it 'updates a webcam feed URL' do
it "updates a webcam feed URL" do
# Create a webcam feed first....
sign_in user
feed = WebcamFeed.create! name: "wow",
device: user.device,
url: "bar.jpg"
input = { url: "/foo.jpg", name: "ok", format: :json, id: feed.id }
patch :update, params: input
feed = WebcamFeed.create! name: "wow",
device: user.device,
url: "bar.jpg"
input = { url: "/foo.jpg", name: "ok" }
patch :update, body: input.to_json, params: { format: :json, id: feed.id }
expect(response.status).to eq(200)
expect(json[:url]).to eq("/foo.jpg")
expect(json[:name]).to eq("ok")

View File

@ -4,7 +4,7 @@ describe CeleryScript::AstNode do
FIXTURE_FILE = File.read("./spec/lib/celery_script/ast_fixture2.json")
let(:hash) do
JSON.parse(FIXTURE_FILE).deep_symbolize_keys
JSON.parse(FIXTURE_FILE, symbolize_names: true)
end
let (:node) { CeleryScript::AstNode.new(**hash) }

View File

@ -49,7 +49,7 @@ describe Resources::Preprocessor do
expect(err.last[:routing_key]).to be_kind_of(String)
dev_id = err.last[:routing_key].split(".").second
expect(dev_id).to eq("device_#{props[:device_id]}")
body = JSON.parse(err.first).deep_symbolize_keys
body = JSON.parse(err.first, symbolize_names: true)
expect(body[:kind]).to eq("rpc_error")
expect(body[:args]).to be_kind_of(Hash)
expect(body[:body]).to be_kind_of(Array)

View File

@ -86,7 +86,7 @@ RSpec.configure do |config|
end
config.color = true
config.fail_fast = 10
# config.fail_fast = 10
config.backtrace_exclusion_patterns = [/gems/]
config.filter_run_excluding type: :feature unless DO_INTEGRATION
config.include Helpers

View File

@ -1,5 +1,5 @@
class Hash
def traverse(parent=nil, &blk)
def traverse(parent = nil, &blk)
each do |k, v|
Hash === v ? v.traverse(k, &blk) : blk.call([parent, k, v])
end
@ -7,9 +7,9 @@ class Hash
end
module Helpers
MAGIC_NUMBER_SEQ_ID = "9999"
MAGIC_NUMBER_SEQ_ID = "9999"
MAGIC_NUMBER_TOOL_ID = "8888"
AST_FIXTURE = File.read("./spec/lib/celery_script/ast_fixture3.json")
AST_FIXTURE = File.read("./spec/lib/celery_script/ast_fixture3.json")
def last_email
ActionMailer::Base.deliveries.last
@ -35,8 +35,8 @@ module Helpers
sid = FakeSequence.create(device: device).id
tid = FactoryBot.create(:tool, device: device).id
str = AST_FIXTURE
.gsub(MAGIC_NUMBER_SEQ_ID, sid.to_s)
.gsub(MAGIC_NUMBER_TOOL_ID, tid.to_s)
.gsub(MAGIC_NUMBER_SEQ_ID, sid.to_s)
.gsub(MAGIC_NUMBER_TOOL_ID, tid.to_s)
JSON.parse(str)["body"]
end
@ -44,18 +44,12 @@ module Helpers
# For when you're actually testing the login UI components. Otherwise,
# consider using the devise test helper `sign_in`
visit new_user_session_path
fill_in 'user_email', with: user.email
fill_in 'user_password', with: user.password
click_button 'Sign in'
fill_in "user_email", with: user.email
fill_in "user_password", with: user.password
click_button "Sign in"
end
def json
json = JSON.parse(response.body)
if json.is_a?(Array)
json.map(&:deep_symbolize_keys!)
else
json.deep_symbolize_keys!
end
JSON.parse(response.body, symbolize_names: true)
end
end