Files
ubicloud/routes/project/location/firewall.rb
Jeremy Evans dc556a684c Use handle_validation_failure in the firewall attach/detach subnet route
This avoids the separate exception handling for web requests. The
api request handling is better here as it shows an error for the
specific field. It's also simpler. You can only hit an error in
the web case if the attached subnets are modified after the page
was displayed, or the user is manually changing them.
2025-08-08 01:52:14 +09:00

119 lines
3.7 KiB
Ruby

# frozen_string_literal: true
class Clover
hash_branch(:project_location_prefix, "firewall") do |r|
r.get api? do
firewall_list_api_response(firewall_list_dataset)
end
r.on FIREWALL_NAME_OR_UBID do |firewall_name, firewall_id|
if firewall_name
r.post api? do
check_visible_location
firewall_post(firewall_name)
end
filter = {Sequel[:firewall][:name] => firewall_name}
else
filter = {Sequel[:firewall][:id] => UBID.to_uuid(firewall_id)}
end
filter[:location_id] = @location.id
@firewall = firewall = @project.firewalls_dataset.first(filter)
check_found_object(firewall)
r.is do
r.delete do
authorize("Firewall:delete", firewall.id)
ds = firewall.private_subnets_dataset
unless ds.exclude(id: dataset_authorize(ds, "PrivateSubnet:edit").select(:id)).empty?
fail Authorization::Unauthorized
end
DB.transaction do
firewall.destroy
audit_log(firewall, "destroy")
end
204
end
r.get do
authorize("Firewall:view", firewall.id)
if api?
Serializers::Firewall.serialize(firewall, {detailed: true})
else
view "networking/firewall/show"
end
end
end
r.post %w[attach-subnet detach-subnet] do |action|
authorize("Firewall:view", firewall.id)
handle_validation_failure("networking/firewall/show")
unless (private_subnet = authorized_private_subnet(location_id: @location.id, perm: "PrivateSubnet:edit"))
fail Validation::ValidationFailed.new({private_subnet_id: "Private subnet with the given id \"#{typecast_params.str("private_subnet_id")}\" and the location \"#{@location.display_name}\" is not found"})
end
actioned = nil
DB.transaction do
if action == "attach-subnet"
firewall.associate_with_private_subnet(private_subnet)
audit_log(firewall, "associate", private_subnet)
actioned = "attached to"
else
firewall.disassociate_from_private_subnet(private_subnet)
audit_log(firewall, "disassociate", private_subnet)
actioned = "detached from"
end
end
if api?
Serializers::Firewall.serialize(firewall, {detailed: true})
else
flash["notice"] = "Private subnet #{private_subnet.name} is #{actioned} the firewall"
r.redirect "#{@project.path}#{firewall.path}"
end
end
r.api do
r.hash_branches(:project_location_firewall_prefix)
end
r.on "firewall-rule" do
r.post true do
authorize("Firewall:edit", firewall.id)
handle_validation_failure("networking/firewall/show")
parsed_cidr = Validation.validate_cidr(typecast_params.str!("cidr"))
port_range = Validation.validate_port_range(typecast_params.str("port_range"))
pg_range = Sequel.pg_range(port_range.first..port_range.last)
DB.transaction do
firewall_rule = firewall.insert_firewall_rule(parsed_cidr.to_s, pg_range)
audit_log(firewall_rule, "create", firewall)
end
flash["notice"] = "Firewall rule is created"
r.redirect "#{@project.path}#{firewall.path}"
end
r.delete :ubid_uuid do |id|
authorize("Firewall:edit", firewall.id)
next 204 unless (fwr = firewall.firewall_rules_dataset[id:])
DB.transaction do
firewall.remove_firewall_rule(fwr)
audit_log(fwr, "destroy")
end
{message: "Firewall rule deleted"}
end
end
end
end
end