stricter JSON validation
parent
ed24e82c81
commit
bf69ae09bd
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue