Module:Layout/Production/Interface/Security
Uiterlijk

De Module:Layout is bedoeld om snel, consistent en uitgebreid een pagina op te maken.
Er is een op de module afgestemde handleiding over deze onderwijswiki beschikbaar.
De module wordt geïnitialiseerd met de configuratie in Module:Layout/Production/Configuration.
Test
[bewerken]Deze module wordt getest door Module:Layout/Production/Test/Security.
All 5 tests are ok.
| Name | Expected | Actual | |
|---|---|---|---|
| test_security_authentication | |||
| test_security_declaration | |||
| test_security_frisk | |||
| test_security_invalid_call | |||
| test_security_scan |
Code
[bewerken]-- Security validates the input passed to Module:Layout before rendering starts.
-- It records user-facing mistakes and sets call.pass to false when rendering
-- should be blocked.
local security = {};
local frisk = {};
local report = {};
-- Check whether this environment was invoked through its configured template.
function security.authentication( call )
if not call or type(call) ~= "table" or not call.include then return call; end
call.add_new_debug( call.message.DEBUG.INVOKER, tostring( call.invoker ), report.debugging( call ) );
if ( call.invoker ~= call.template ) then
call.add_new_mistake ( call.message.MISTAKE.NO_INTERFACE_TEMPLATE );
call.add_debug( call.message.DEBUG.NO_INTERFACE_TEMPLATE );
end
return call;
end
-- Check internal #invoke parameter names before translated template names are handled.
function security.declaration( call )
if not call or type(call) ~= "table" or not call.include then return call; end
-- Array search is used to compare against the configured parameter whitelist.
local array = call.include( "array" );
-- Named #invoke parameters must be listed in hook.PARAMETER.
for key, value in pairs( call.named ) do
if not array.search( call.hook.PARAMETER, key, true ) then
call.add_new_mistake ( call.message.MISTAKE.WRONG.INVOKE_PARAMETER, key, key, value );
end
end
return call;
end
-- Validate all configured parameter values after names have been accepted.
function security.frisk( call )
if not call or type(call) ~= "table" or not call.include then return call; end
-- Each parameter has an optional frisk function with its own value rules.
local array, frisk = call.include( "array", "frisk" );
local mistakes_before_value_check = #call.mistake;
for _, parameter in ipairs( call.hook.PARAMETER ) do
-- Optimized: Pass the call object directly instead of deep-copying it 15+ times.
local mistake, m1, m2, m3, m4, m5, m6 = frisk[ parameter ]( call );
if mistake then
call.add_new_mistake( mistake, m1, m2, m3, m4, m5, m6 );
end
end
local value_mistake = #call.mistake - mistakes_before_value_check;
if value_mistake == 0 then call.add_debug( call.message.DEBUG.VALUES_OK ); end
if value_mistake == 1 then call.add_mistake( call.message.DEBUG.VALUE_MISTAKE ); end
if value_mistake > 1 then call.add_mistake( call.message.DEBUG.VALUE_MISTAKES, value_mistake ); end
return call;
end
-- Scan the original page wikitext for translated template parameter names.
-- A page may contain multiple template calls, so every matching call is checked.
function security.scan( call ) -- returns call object with security information
if not call or type(call) ~= "table" or not call.include then return call; end
-- Memory optimization: Skip expensive wikitext scanning in production.
if call.environment == "production" then return call; end
local extract, array = call.include( "extract", "array" );
-- Module documentation can expose source text containing template definitions,
-- which would produce false positives if scanned as normal page content.
-- if call.caller:inNamespace( "Module" ) and call.caller.subpageText ~= "doc" then return call; end
call.add_new_debug( call.message.DEBUG.CALLER, tostring( call.invoker), tostring( call.caller ) );
local caller_content = call.caller:getContent();
local calling_templates = extract.template( caller_content, call.message.TEMPLATENAME, call );
local parameter_mistake = {};
for index, value in ipairs( calling_templates ) do
for key, v in pairs( value ) do
-- Unnamed parameters remain free-form; named parameters must be localized hooks.
if not tonumber( key ) and not array.search( call.message.HOOK.PARAMETER, key, true ) then
parameter_mistake[ #parameter_mistake + 1 ] = key;
call.add_new_mistake( call.message.MISTAKE.WRONG.TEMPLATE_PARAMETER, key, key, v, table.concat( call.message.HOOK.PARAMETER, ", ") );
end
end
end
-- The mistakes are already stored. The debug reports only the number of mistakes found.
if #parameter_mistake == 0 then call.add_debug( call.message.DEBUG.PARAMETERS_OK ); end
if #parameter_mistake == 1 then call.add_debug( call.message.DEBUG.PARAMETER_MISTAKE, parameter_mistake[1] ); end
if #parameter_mistake > 1 then call.add_debug( call.message.DEBUG.PARAMETER_MISTAKES, #parameter_mistake, table.concat( parameter_mistake, ", ") ); end
return call;
end
-- Reconstruct the #invoke call for debug feedback.
function report.debugging( call )
if not call or type(call) ~= "table" then return ""; end
local call_string = "{{#invoke:Layout|main";
-- Add named parameters.
if type(call.named) == "table" then
for key, value in pairs( call.named ) do
call_string = call_string .. "|" .. key .. "=" .. value;
end
end
-- Add unnamed parameters.
if type(call.unnamed) == "table" then
for _, value in ipairs( call.unnamed ) do
call_string = call_string .. "|" .. value;
end
end
return call_string .. "}}";
end
return security;