Skip to content

Commit

Permalink
Merge 1756196 into 22fb06c
Browse files Browse the repository at this point in the history
  • Loading branch information
mvidner committed Sep 10, 2018
2 parents 22fb06c + 1756196 commit f5ad4e9
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 41 deletions.
1 change: 1 addition & 0 deletions src/lib/y2firewall/widgets/allowed_services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class AllowedServices < ::CWM::CustomWidget
#
# @param zone [Y2Firewall::Firewalld::Zone] Zone
def initialize(zone)
textdomain "firewall"
@zone = zone
self.widget_id = "allowed_services"
@available_svcs_table = ServicesTable.new
Expand Down
1 change: 1 addition & 0 deletions src/lib/y2firewall/widgets/pages/interfaces.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def contents
class ZoneBox < CWM::SelectionBox
# @param interface [Hash<String,String>] "id", "name" and "zone"
def initialize(interface)
textdomain "firewall"
@interface = interface
@zones = Y2Firewall::Firewalld.instance.zones
end
Expand Down
116 changes: 75 additions & 41 deletions src/lib/y2firewall/widgets/pages/zone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
# ------------------------------------------------------------------------------

require "yast"
require "cwm/common_widgets"
require "cwm/page"
require "cwm/table"
require "cwm/tabs"
require "y2firewall/widgets/allowed_services"

Expand Down Expand Up @@ -72,60 +74,92 @@ def label

def contents
VBox(
# TRANSLATORS: TCP is the Transmission Control Protocol
PortsForProtocol.new(@zone, _("TCP Ports"), :tcp),
# TRANSLATORS: UDP is the User Datagram Protocol
PortsForProtocol.new(@zone, _("UDP Ports"), :udp),
# TRANSLATORS: SCTP is the Stream Control Transmission Protocol
PortsForProtocol.new(@zone, _("SCTP Ports"), :sctp),
# TRANSLATORS: DCCP is the Datagram Congestion Control Protocol
PortsForProtocol.new(@zone, _("DCCP Ports"), :dccp),
PortsForProtocols.new(@zone),
VStretch()
)
end

def help
"FIXME: ports or port ranges, separated by spaces and/or commas <br>" \
"a port is an integer <br>" \
"a port range is port-dash-port (with no spaces)"
end

def init
log.info "INIT #{widget_id}"
end
# A group of InputFields to specify the open TCP, UDP, SCTP and DCCP ports.
class PortsForProtocols < CWM::CustomWidget
extend Yast::I18n

def store
log.info "STORE #{widget_id}"
end
PROTOCOLS = {
# TRANSLATORS: TCP is the Transmission Control Protocol
tcp: N_("TCP Ports"),
# TRANSLATORS: UDP is the User Datagram Protocol
udp: N_("UDP Ports"),
# TRANSLATORS: SCTP is the Stream Control Transmission Protocol
sctp: N_("SCTP Ports"),
# TRANSLATORS: DCCP is the Datagram Congestion Control Protocol
dccp: N_("DCCP Ports")
}.freeze

# FIXME: separate objects like this do not work well with the
# single zone.ports attribute mixing all protos. Rather make a
# CustomWidget that handles it all
class PortsForProtocol < CWM::InputField
# @param proto [:tcp,:udp,:sctp,:dccp]
def initialize(zone, label, proto)
def initialize(zone)
textdomain "firewall"
@zone = zone
@proto = proto
@label = label
self.widget_id = "#{proto}_ports"
end

attr_reader :label
def contents
fields = PROTOCOLS.map do |sym, label|
InputField(Id(sym), Opt(:hstretch), _(label))
end
VBox(* fields)
end

def help
"FIXME: ports or port ranges, separated by spaces and/or commas <br>" \
"a port is an integer <br>" \
"a port range is port-dash-port (with no spaces)"
end

def init
log.info "INIT #{widget_id}"
# FIXME: factor out and test
self.value = @zone.ports
.map { |p| p.split("/") }
.find_all { |_port, proto| proto == @proto.to_s }
.map { |port, _proto| port }
.join(", ")
by_proto = ports_from_array(@zone.ports)
PROTOCOLS.each do |sym, _label|
Yast::UI.ChangeWidget(Id(sym), :Value, by_proto.fetch(sym, []).join(", "))
end
end

# FIXME: validation, cleanup, error reporting
def store
# FIXME: do modify immediately?
# DUH, clumsy
log.info "STORE #{widget_id}"
by_proto = PROTOCOLS.map do |sym, _label|
line = Yast::UI.QueryWidget(Id(sym), :Value)
[sym, items_from_ui(line)]
end
@zone.ports = ports_to_array(by_proto.to_h)
end

private

def items_from_ui(s)
# the separator is at least one comma or space, surrounded by optional spaces
s.split(/ *[, ] */)
end

# @return [String] ports specification as array
# @param hash [Hash{Symbol => Array<String>}] ports specification broken by protocol
# @example
# h = { tcp: ["55555-55666", "44444"], udp: ["33333"] }
# a = ["55555-55666/tcp", "44444/tcp", "33333/udp"]
# ports_to_array(h) # => a
def ports_to_array(hash)
hash.map { |sym, ports| ports.map { |p| "#{p}/#{sym}" } }.flatten
end

# @param s [String] ports specification as one string
# @return [Hash{Symbol => Array<String>}] ports specification broken by protocol
# @example
# a = ["55555-55666/tcp", "44444/tcp", "33333/udp"]
# h = { tcp: ["55555-55666", "44444"], udp: ["33333"] }
# ports_from_array(a) # => h
def ports_from_array(a)
a
.map { |p| p.split("/") }
.each_with_object({}) do |i, acc|
ports, proto = *i
proto = proto.to_sym
acc[proto] ||= []
acc[proto] << ports
end
end
end
end
Expand Down Expand Up @@ -176,5 +210,5 @@ def init
end
end
end
end
end
end
2 changes: 2 additions & 0 deletions src/lib/y2firewall/widgets/pages/zones.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
module Y2Firewall
module Widgets
module Pages
# A page for firewall zones:
# contains {ZonesTable}, has {Zone} as subpages.
class Zones < CWM::Page
# Constructor
#
Expand Down
1 change: 1 addition & 0 deletions src/lib/y2firewall/widgets/services_table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

module Y2Firewall
module Widgets
# A table with all firewall services.
class ServicesTable < ::CWM::Table
# @!attribute [r] services
# @return [Array<String>] Services to be displayed
Expand Down
1 change: 1 addition & 0 deletions src/lib/y2firewall/widgets/zones_table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

module Y2Firewall
module Widgets
# A table with all {Y2Firewall::Firewalld::Zone}s.
class ZonesTable < ::CWM::Table
# @!attribute [r] zone
# @return [Array<Y2Firewall::Firewalld::Zone>] Zones
Expand Down
61 changes: 61 additions & 0 deletions test/lib/y2firewall/widgets/pages/zone_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env rspec

# ------------------------------------------------------------------------------
# Copyright (c) 2018 SUSE LLC
#
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of version 2 of the GNU General Public License as published by the
# Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, contact SUSE.
#
# To contact SUSE about this file by physical or electronic mail, you may find
# current contact information at www.suse.com.
# ------------------------------------------------------------------------------

require_relative "../../../../test_helper.rb"
require "cwm/rspec"
require "y2firewall/widgets/pages/zone"

describe Y2Firewall::Widgets::Pages::PortsTab::PortsForProtocols do
subject { described_class.new(double("fake zone")) }

describe "#items_from_ui" do
let(:expected) do
["11/tcp", "12/udp", "13/udp"]
end

it "parses comma separated items" do
expect(subject.send(:items_from_ui, "11/tcp,12/udp,13/udp")).to eq(expected)
end

it "parses space separated items" do
expect(subject.send(:items_from_ui, "11/tcp 12/udp 13/udp")).to eq(expected)
end

it "parses clumsily separated items" do
expect(subject.send(:items_from_ui, "11/tcp 12/udp , 13/udp")).to eq(expected)
end
end

let(:ports_h1) { { tcp: ["55555-55666", "44444"], udp: ["33333"] } }
let(:ports_a1) { ["55555-55666/tcp", "44444/tcp", "33333/udp"] }

describe "#ports_from_array" do
it "parses a regular case" do
expect(subject.send(:ports_from_array, ports_a1)).to eq(ports_h1)
end
end

describe "#ports_to_array" do
it "formats a regular case" do
expect(subject.send(:ports_to_array, ports_h1)).to eq(ports_a1)
end
end
end

0 comments on commit f5ad4e9

Please sign in to comment.