Module:Sensitive IP addresses/list/validate
Appearance
This module validates the data in Module:Sensitive IP addresses/list.
-- This module validates the data in [[Module:Sensitive IP addresses/list]].
-- Load modules
local mSensitiveIPs = require('Module:Sensitive IP addresses')
local Subnet = require('Module:IP').Subnet
-- Constants
local DATA_MODULE = 'Module:Sensitive IP addresses/list'
local p = {}
local function makeErrorLogger()
-- Return an object for formatting errors.
return {
errors = {},
addError = function (self, msg, ...)
table.insert(self.errors, string.format(msg, ...))
end,
addEntryTypeError = function (self, entryIdx, field, actual, expected)
self:addError(
'The %s field in data entry #%d was type %s (should be string or nil)',
field, entryIdx, actual, expected
)
end,
hasErrors = function (self)
return #self.errors > 0
end,
makeReport = function (self)
if #self.errors < 1 then
return 'No errors found'
else
local ret = {'Found the following errors:'}
for i, msg in ipairs(self.errors) do
ret[#ret + 1] = string.format('* <strong class="error">%s</strong>', msg)
end
return table.concat(ret, '\n')
end
end,
}
end
local function loadData(logger)
-- Load the data table, logging any errors in the process.
-- Check whether the data module can be successfully loaded.
local success, data = pcall(mw.loadData, DATA_MODULE)
if not success then
logger:addError('%s could not be parsed by mw.loadData; check for [[mw:LUAREF#mw.loadData|invalid data]]', DATA_MODULE)
return nil
end
-- Check that the data table is a table.
if type(data) ~= 'table' then
logger:addError('%s returned a %s; table expected', DATA_MODULE, type(data))
end
return data
end
local function checkDataStructure(logger, data)
-- Checks the structure of individual entries.
for dataIndex, subtable in ipairs(data) do
-- Check that subtables are tables.
if type(subtable) ~= 'table' then
logger:addError('Data entry #%d is not a table', dataIndex)
end
-- Check that we have a name for the entry.
if type(subtable.name) ~= 'string' then
logger:addError('Data entry #%d does not have a name field', dataIndex)
elseif subtable.name == '' then
logger:addError('Data entry #%d has a blank name field', dataIndex)
end
-- Check that optional string fields are strings if they are present.
for _, field in ipairs{'description', 'notes'} do
local val = subtable[field]
if val ~= nil and type(val) ~= 'string' then
logger:addEntryTypeError(dataIndex, field, type(val), 'string or nil')
end
end
-- Check that the reason is valid if it is present.
if subtable.reason ~= nil then
if type(subtable.reason) ~= 'string' then
logger:addEntryTypeError(
dataIndex,
'reason',
type(subtable.reason),
'string or nil'
)
elseif not mSensitiveIPs.isValidSensitivityReason(subtable.reason) then
logger:addError(
"The reason field in data entry #%d was invalid (should be '%s')",
dataIndex,
mw.text.listToText(
mSensitiveIPs.getSensitivityReasons,
"', '",
"', or '"
)
)
end
end
-- Check IP range tables.
for i, field in ipairs{'ipv4Ranges', 'ipv6Ranges'} do
local ranges = subtable[field]
if ranges ~= nil then
if type(ranges) ~= 'table' then
logger:addEntryTypeError(dataIndex, field, type(ranges), 'table or nil')
else
for j, range in ipairs(ranges) do
if type(range) ~= 'string' then
logger:addError(
'Range #%d in the %s field of entry #%d was type %s (expected string)',
j, field, type(range)
)
elseif range == '' then
logger:addError(
'Range #%d in the %s field of entry #%d was a blank string',
j, field
)
end
end
end
end
end
end
end
function p.main()
local logger = makeErrorLogger()
local data = loadData(logger)
if logger:hasErrors() then
return logger:makeReport()
end
checkDataStructure(logger, data)
return logger:makeReport()
end
return p