Audit logging is designed to be simple to use. You call the audit_log method with the object affected and the action taken on it: ```ruby audit_log(vm, "create") ``` If additional objects are affected by the same action, then you can include them in the third argument: ```ruby audit_log(ps, "connect", subnet) ``` This implements an audit logging check similar to the recently added authorization check. All successful non-GET requests to the application are checked for audit logging, and will fail in non-frozen tests if an audit logging method is not called. Currently, only create/destroy actions are logged. Audit logging in other cases is ignored. However, this approach was necessary to check that no cases that should result in audit logging were missed. It also allows for easily flipping the switch to audit log all route actions.
115 lines
3.4 KiB
Ruby
115 lines
3.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative "spec_helper"
|
|
|
|
RSpec.describe Clover do
|
|
it "handles CSRF token errors" do
|
|
visit "/login"
|
|
find(".rodauth input[name=_csrf]", visible: false).set("")
|
|
click_button "Sign in"
|
|
|
|
expect(page.status_code).to eq(400)
|
|
expect(page).to have_flash_error("An invalid security token submitted with this request, please try again")
|
|
end
|
|
|
|
it "does not redirect to requested path if path is too long" do
|
|
create_account
|
|
visit("/a" * 2048)
|
|
expect(page.status_code).to eq(200)
|
|
expect(page).to have_current_path("/login", ignore_query: true)
|
|
fill_in "Email Address", with: TEST_USER_EMAIL
|
|
fill_in "Password", with: TEST_USER_PASSWORD
|
|
click_button "Sign in"
|
|
expect(page.title).to end_with("Dashboard")
|
|
end
|
|
|
|
if ENV["CLOVER_FREEZE"] != "1"
|
|
it "raises error if no_authorization_needed called when not needed or already authorized" do
|
|
create_account.create_project_with_default_policy("project-1")
|
|
login
|
|
|
|
visit "/test-no-authorization-needed/once"
|
|
expect(page.status_code).to eq(200)
|
|
|
|
re = /called no_authorization_needed when authorization already not needed: /
|
|
expect { visit "/test-no-authorization-needed/twice" }.to raise_error(RuntimeError, re)
|
|
expect { visit "/test-no-authorization-needed/after-authorization" }.to raise_error(RuntimeError, re)
|
|
expect { visit "/test-no-authorization-needed/runtime-error" }.to raise_error(RuntimeError, /no authorization check for /)
|
|
end
|
|
|
|
it "raises error for non-GET request without audit logging" do
|
|
expect { post "/webhook/test-no-audit-logging/test" }.to raise_error(RuntimeError, /no audit logging for /)
|
|
end
|
|
end
|
|
|
|
it "raises error for unsupported audit log action" do
|
|
expect { post "/webhook/test-no-audit-logging/bad" }.to raise_error(RuntimeError, "unsupported audit_log action: bad_action")
|
|
end
|
|
|
|
it "handles expected errors" do
|
|
expect(Clog).to receive(:emit).with("route exception").and_call_original
|
|
|
|
visit "/webhook/test-error"
|
|
|
|
expect(page.title).to eq("Ubicloud - UnexceptedError")
|
|
end
|
|
|
|
it "raises unexpected errors in test environment" do
|
|
expect(Clog).not_to receive(:emit)
|
|
|
|
expect { visit "/webhook/test-error?message=treat+as+unexpected+error" }.to raise_error(RuntimeError, "treat as unexpected error")
|
|
end
|
|
|
|
it "raises validation error if a required parameter is not present" do
|
|
create_account
|
|
login
|
|
visit("/test-missing-request-params")
|
|
|
|
# Validation error without referrer redirects to /, which redirects to default project dashboard
|
|
expect(page.title).to eq("Ubicloud - Default Dashboard")
|
|
end
|
|
|
|
it "does not have broken links" do
|
|
create_account
|
|
login
|
|
|
|
visited = {"" => true}
|
|
failures = []
|
|
queue = Queue.new
|
|
queue.push([nil, "/"])
|
|
|
|
pop = lambda do
|
|
queue.pop(true)
|
|
rescue ThreadError
|
|
end
|
|
|
|
while (tuple = pop.call)
|
|
from, path = tuple
|
|
|
|
next if visited[path]
|
|
visited[path] = true
|
|
visit path
|
|
|
|
if page.status_code == 404
|
|
failures << [from, path]
|
|
end
|
|
|
|
if page.response_headers["content-type"].include?("text/html")
|
|
links = page.all("a").map do |a|
|
|
a["href"].sub(/#.*\z/, "")
|
|
end
|
|
|
|
links.reject! do |path|
|
|
path.empty? || path.start_with?(%r{https://|mailto:})
|
|
end
|
|
|
|
links.each do |path|
|
|
queue.push [page.current_path, path]
|
|
end
|
|
end
|
|
end
|
|
|
|
expect(failures).to be_empty
|
|
end
|
|
end
|