Create config screen for reCAPTCHA in spamfilter module

This commit is contained in:
Kijin Sung 2020-10-01 14:42:07 +09:00
parent 9c60a8932c
commit c7c03d3c37
13 changed files with 283 additions and 30 deletions

View file

@ -5,12 +5,14 @@
<action name="dispSpamfilterAdminDeniedIPList" type="view" admin_index="true" menu_name="spamFilter" menu_index="true" />
<action name="dispSpamfilterAdminDeniedWordList" type="view" menu_name="spamFilter" />
<action name="dispSpamfilterAdminConfigBlock" type="view" menu_name="spamFilter" />
<action name="dispSpamfilterAdminConfigCaptcha" type="view" menu_name="spamFilter" />
<action name="procSpamfilterAdminInsertDeniedIP" type="controller" />
<action name="procSpamfilterAdminDeleteDeniedIP" type="controller" />
<action name="procSpamfilterAdminInsertDeniedWord" type="controller" />
<action name="procSpamfilterAdminDeleteDeniedWord" type="controller" />
<action name="procSpamfilterAdminInsertConfig" type="controller" ruleset="insertConfig" />
<action name="procSpamfilterAdminInsertConfigCaptcha" type="controller" />
</actions>
<menus>
<menu name="spamFilter" tyle="super">

View file

@ -2,6 +2,7 @@
$lang->cmd_denied_ip = 'IP Address Blacklist';
$lang->cmd_denied_word = 'Keyword Blacklist';
$lang->cmd_config_block = 'Automatic Blocking';
$lang->cmd_captcha_config = 'CAPTCHA';
$lang->add_denied_ip = 'Add IP address or range';
$lang->add_denied_word = 'Add keyword';
$lang->spamfilter = 'Spam Filter';
@ -42,3 +43,23 @@ $lang->msg_duplicate = 'Duplicate';
$lang->msg_invalid_ip = 'Invalid IP address format.';
$lang->msg_invalid_word = 'Spam keywords must be between 2 and 180 characters.';
$lang->msg_faillist = '<br />Error (already blocked)<br /> %s ';
$lang->use_captcha = 'Use CAPTCHA';
$lang->recaptcha_theme = 'Color Theme';
$lang->recaptcha_theme_light = 'Light';
$lang->recaptcha_theme_dark = 'Dark';
$lang->recaptcha_size = 'Display Size';
$lang->recaptcha_size_normal = 'Normal';
$lang->recaptcha_size_compact = 'Compact';
$lang->recaptcha_target_devices = 'Target Devices';
$lang->recaptcha_target_actions = 'Target Actions';
$lang->recaptcha_target_document = 'Document Post';
$lang->recaptcha_target_comment = 'Comment Post';
$lang->recaptcha_target_users = 'Target Users';
$lang->recaptcha_target_guest = 'Guests Only';
$lang->recaptcha_target_everyone = 'Everyone';
$lang->recaptcha_target_frequency = 'Frequency';
$lang->recaptcha_target_first_time_only = 'First Time Only';
$lang->recaptcha_target_every_time = 'Every Time';
$lang->msg_recaptcha_connection_error = 'An error occurred while connecting to the reCAPTCHA verification server.';
$lang->msg_recaptcha_server_error = 'An error occurred while verifying your reCAPTCHA response.';
$lang->msg_recaptcha_invalid_response = 'Please check reCAPTCHA.';

View file

@ -2,6 +2,7 @@
$lang->cmd_denied_ip = '스팸 IP 목록';
$lang->cmd_denied_word = '스팸 키워드 목록';
$lang->cmd_config_block = '자동 차단 설정';
$lang->cmd_captcha_config = '캡챠 설정';
$lang->add_denied_ip = '스팸 IP 추가';
$lang->add_denied_word = '스팸 키워드 추가';
$lang->spamfilter = '스팸필터';
@ -42,3 +43,23 @@ $lang->msg_duplicate = '이미 존재합니다.';
$lang->msg_invalid_ip = 'IP 주소 형식이 올바르지 않습니다.';
$lang->msg_invalid_word = '스팸 키워드는 2~180자 사이여야 합니다.';
$lang->msg_faillist = '<br />실패 (이미 차단되어 있습니다)<br /> %s ';
$lang->use_captcha = '캡챠 사용';
$lang->recaptcha_theme = '색상 테마';
$lang->recaptcha_theme_light = '밝은 색상';
$lang->recaptcha_theme_dark = '어두운 색상';
$lang->recaptcha_size = '캡챠 크기';
$lang->recaptcha_size_normal = '일반';
$lang->recaptcha_size_compact = '작게';
$lang->recaptcha_target_devices = '적용 대상 기기';
$lang->recaptcha_target_actions = '적용 대상 액션';
$lang->recaptcha_target_document = '글 쓰기';
$lang->recaptcha_target_comment = '댓글 쓰기';
$lang->recaptcha_target_users = '적용 대상 유저';
$lang->recaptcha_target_guest = '비회원만';
$lang->recaptcha_target_everyone = '모든 사용자';
$lang->recaptcha_target_frequency = '캡챠 사용 빈도';
$lang->recaptcha_target_first_time_only = '최초 1회만 사용';
$lang->recaptcha_target_every_time = '매번 사용';
$lang->msg_recaptcha_connection_error = 'reCAPTCHA 스팸방지 서버에 접속하는 도중 오류가 발생했습니다.';
$lang->msg_recaptcha_server_error = 'reCAPTCHA 스팸방지 서버와 통신하는 도중 오류가 발생했습니다.';
$lang->msg_recaptcha_invalid_response = 'reCAPTCHA 스팸방지 기능을 체크해 주십시오.';

View file

@ -16,8 +16,11 @@ class spamfilterAdminController extends spamfilter
function procSpamfilterAdminInsertConfig()
{
// Get current config
$config = ModuleModel::getModuleConfig('spamfilter') ?: new stdClass;
// Get the default information
$args = Context::gets('limits', 'limits_interval', 'limits_count', 'check_trackback', 'ipv4_block_range', 'ipv6_block_range', 'display_keyword', 'custom_message');
$args = Context::gets('limits', 'limits_interval', 'limits_count', 'check_trackback', 'ipv4_block_range', 'ipv6_block_range', 'custom_message');
// Set default values
if($args->limits != 'Y')
@ -38,10 +41,15 @@ class spamfilterAdminController extends spamfilter
}
$args->limits_interval = intval($args->limits_interval);
$args->limits_count = intval($args->limits_count);
$args->custom_message = escape(utf8_trim($args->custom_message));
foreach ($args as $key => $val)
{
$config->$key = $val;
}
// Create and insert the module Controller object
$oModuleController = getController('module');
$moduleConfigOutput = $oModuleController->insertModuleConfig('spamfilter', $args);
$moduleConfigOutput = $oModuleController->insertModuleConfig('spamfilter', $config);
if(!$moduleConfigOutput->toBool())
{
return $moduleConfigOutput;
@ -52,6 +60,50 @@ class spamfilterAdminController extends spamfilter
$this->setRedirectUrl($returnUrl);
}
function procSpamfilterAdminInsertConfigCaptcha()
{
// Get current config
$config = ModuleModel::getModuleConfig('spamfilter') ?: new stdClass;
// Get updated values
$vars = Context::getRequestVars();
// Check values
if (!isset($config->captcha))
{
$config->captcha = new stdClass;
}
$config->captcha->type = $vars->captcha_type === 'recaptcha' ? 'recaptcha' : 'none';
$config->captcha->site_key = escape(utf8_trim($vars->site_key));
$config->captcha->secret_key = escape(utf8_trim($vars->secret_key));
$config->captcha->theme = escape(utf8_trim($vars->captcha_theme));
$config->captcha->size = escape(utf8_trim($vars->captcha_size));
$config->captcha->target_devices = [
'pc' => in_array('pc', $vars->target_devices) ? true : false,
'mobile' => in_array('mobile', $vars->target_devices) ? true : false,
];
$config->captcha->target_actions = [
'signup' => in_array('signup', $vars->target_actions) ? true : false,
'login' => in_array('login', $vars->target_actions) ? true : false,
'recovery' => in_array('recovery', $vars->target_actions) ? true : false,
'document' => in_array('document', $vars->target_actions) ? true : false,
'comment' => in_array('comment', $vars->target_actions) ? true : false,
];
$config->captcha->target_users = escape(utf8_trim($vars->target_users)) ?: 'non_members';
$config->captcha->target_frequency = escape(utf8_trim($vars->target_frequency)) ?: 'first_time_only';
// Insert new config
$output = getController('module')->insertModuleConfig('spamfilter', $config);
if(!$output->toBool())
{
return $output;
}
$this->setMessage('success_updated');
$returnUrl = Context::get('success_return_url') ? Context::get('success_return_url') : getNotEncodedUrl('', 'module', 'admin', 'act', 'dispSpamfilterAdminConfigCaptcha');
$this->setRedirectUrl($returnUrl);
}
function procSpamfilterAdminInsertDeniedIP()
{
//스팸IP 추가

View file

@ -70,13 +70,22 @@ class spamfilterAdminView extends spamfilter
*/
function dispSpamfilterAdminConfigBlock()
{
// Get configurations (using module model object)
$oModuleModel = getModel('module');
$config = $oModuleModel->getModuleConfig('spamfilter');
$config = ModuleModel::getModuleConfig('spamfilter');
Context::set('config', $config);
$this->setTemplateFile('config_block');
}
/**
* @brief Configure CAPTCHA
*/
function dispSpamfilterAdminConfigCaptcha()
{
$config = ModuleModel::getModuleConfig('spamfilter');
Context::set('config', $config);
$this->setTemplateFile('config_captcha');
}
}
/* End of file spamfilter.admin.view.php */
/* Location: ./modules/spamfilter/spamfilter.admin.view.php */

View file

@ -79,8 +79,8 @@ class spamfilter extends ModuleObject
if(!$oDB->isColumnExists('spamfilter_denied_ip', 'latest_hit')) return true;
if(!$oDB->isColumnExists('spamfilter_denied_ip', 'description')) return true;
$config = ModuleModel::getModuleConfig('spamfilter');
if (!is_object($config) || !isset($config->captcha))
$config = ModuleModel::getModuleConfig('spamfilter') ?: new stdClass;
if (!isset($config->captcha))
{
return true;
}
@ -125,8 +125,8 @@ class spamfilter extends ModuleObject
$oDB->addColumn('spamfilter_denied_ip','description','varchar', 250);
}
$config = ModuleModel::getModuleConfig('spamfilter');
if (!is_object($config) || !isset($config->captcha))
$config = ModuleModel::getModuleConfig('spamfilter') ?: new stdClass;
if (!isset($config->captcha))
{
$config = is_object($config) ? $config : new stdClass;
$recaptcha_config = AddonModel::getAddonConfig('recaptcha');
@ -182,10 +182,7 @@ class spamfilter extends ModuleObject
$output->target_actions = [];
foreach (['signup', 'login', 'recovery', 'document', 'comment'] as $action)
{
if ($config->{'use_' . $action} === 'Y')
{
$output->target_actions[$action] = true;
}
$output->target_actions[$action] = ($config->{'use_' . $action} === 'Y') ? true : false;
}
$output->target_modules = [];
foreach ($config->mid_list as $mid)

View file

@ -19,7 +19,7 @@ class spamfilterModel extends spamfilter
*/
function getConfig()
{
return ModuleModel::getModuleConfig('spamfilter');
return ModuleModel::getModuleConfig('spamfilter') ?: new stdClass;
}
/**

View file

@ -1,10 +1,5 @@
<include target="./header.html" />
<section class="section">
<ul class="x_nav x_nav-tabs">
<li><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedIPList')}">{$lang->cmd_denied_ip}</a></li>
<li><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedWordList')}">{$lang->cmd_denied_word}</a></li>
<li class="x_active"><a href="{getUrl('','module','admin','act','dispSpamfilterAdminConfigBlock')}">{$lang->cmd_config_block}</a></li>
</ul>
<form action="./" method="post" id="spamfilterConfig" class="x_form-horizontal">
<input type="hidden" name="act" value="procSpamfilterAdminInsertConfig" />
<input type="hidden" name="module" value="spamfilter" />
@ -41,7 +36,7 @@
<div class="x_control-group">
<label class="x_control-label" for="custom_message">{$lang->custom_message}</label>
<div class="x_controls">
<textarea name="custom_message" id="custom_message" class="lang_code">{htmlspecialchars($config->custom_message)}</textarea>
<textarea name="custom_message" id="custom_message" class="lang_code">{escape($config->custom_message, false)}</textarea>
<p class="x_help-block">{$lang->about_custom_message}</p>
</div>
</div>

View file

@ -0,0 +1,120 @@
<config autoescape="on" />
<include target="./header.html" />
<section class="section">
<form action="./" method="post" id="spamfilterConfig" class="x_form-horizontal">
<input type="hidden" name="act" value="procSpamfilterAdminInsertConfigCaptcha" />
<input type="hidden" name="module" value="spamfilter" />
<input type="hidden" name="xe_validator_id" value="modules/spamfilter/tpl/2" />
<div class="x_control-group">
<label class="x_control-label" for="captcha_type">{$lang->use_captcha}</label>
<div class="x_controls">
<select id="captcha_type" name="captcha_type">
<option value="none" selected="selected"|cond="$config->captcha->type === 'none'">{$lang->notuse}</option>
<option value="recaptcha" selected="selected"|cond="$config->captcha->type === 'recaptcha'">reCAPTCHA</option>
</select>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label" for="site_key">Site Key</label>
<div class="x_controls">
<input type="text" id="site_key" name="site_key" value="{$config->captcha->site_key}" />
</div>
</div>
<div class="x_control-group">
<label class="x_control-label" for="secret_key">Secret Key</label>
<div class="x_controls">
<input type="text" id="secret_key" name="secret_key" value="{$config->captcha->secret_key}" />
</div>
</div>
<div class="x_control-group">
<label class="x_control-label" for="captcha_theme">{$lang->recaptcha_theme}</label>
<div class="x_controls">
<select id="captcha_theme" name="captcha_theme">
<option value="light" selected="selected"|cond="$config->captcha->theme === 'light'">{$lang->recaptcha_theme_light}</option>
<option value="dark" selected="selected"|cond="$config->captcha->theme === 'dark'">{$lang->recaptcha_theme_dark}</option>
</select>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label" for="captcha_size">{$lang->recaptcha_size}</label>
<div class="x_controls">
<select id="captcha_size" name="captcha_size">
<option value="normal" selected="selected"|cond="$config->captcha->size === 'normal'">{$lang->recaptcha_size_normal}</option>
<option value="compact" selected="selected"|cond="$config->captcha->size === 'compact'">{$lang->recaptcha_size_compact}</option>
</select>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->recaptcha_target_devices}</label>
<div class="x_controls">
<label for="target_devices_pc" class="x_inline">
<input type="checkbox" id="target_devices_pc" name="target_devices[]" value="pc" checked="checked"|cond="$config->captcha->target_devices['pc']" />
{$lang->pc}
</label>
<label for="target_devices_mobile" class="x_inline">
<input type="checkbox" id="target_devices_mobile" name="target_devices[]" value="mobile" checked="checked"|cond="$config->captcha->target_devices['mobile']" />
{$lang->mobile}
</label>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->recaptcha_target_actions}</label>
<div class="x_controls">
<label for="target_actions_signup" class="x_inline">
<input type="checkbox" id="target_actions_signup" name="target_actions[]" value="signup" checked="checked"|cond="$config->captcha->target_actions['signup']" />
{$lang->cmd_signup}
</label>
<label for="target_actions_login" class="x_inline">
<input type="checkbox" id="target_actions_login" name="target_actions[]" value="login" checked="checked"|cond="$config->captcha->target_actions['login']" />
{$lang->cmd_login}
</label>
<label for="target_actions_recovery" class="x_inline">
<input type="checkbox" id="target_actions_recovery" name="target_actions[]" value="recovery" checked="checked"|cond="$config->captcha->target_actions['recovery']" />
{$lang->cmd_find_member_account}
</label>
<label for="target_actions_document" class="x_inline">
<input type="checkbox" id="target_actions_document" name="target_actions[]" value="document" checked="checked"|cond="$config->captcha->target_actions['document']" />
{$lang->recaptcha_target_document}
</label>
<label for="target_actions_comment" class="x_inline">
<input type="checkbox" id="target_actions_comment" name="target_actions[]" value="comment" checked="checked"|cond="$config->captcha->target_actions['comment']" />
{$lang->recaptcha_target_comment}
</label>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->recaptcha_target_users}</label>
<div class="x_controls">
<label for="target_users_1" class="x_inline">
<input type="radio" id="target_users_1" name="target_users" value="non_members" checked="checked"|cond="$config->captcha->target_users === 'non_members'" />
{$lang->recaptcha_target_guest}
</label>
<label for="target_users_2" class="x_inline">
<input type="radio" id="target_users_2" name="target_users" value="everyone" checked="checked"|cond="$config->captcha->target_users === 'everyone'" />
{$lang->recaptcha_target_everyone}
</label>
</div>
</div>
<div class="x_control-group">
<label class="x_control-label">{$lang->recaptcha_target_frequency}</label>
<div class="x_controls">
<label for="target_frequency_1" class="x_inline">
<input type="radio" id="target_frequency_1" name="target_frequency" value="first_time_only" checked="checked"|cond="$config->captcha->target_frequency === 'first_time_only'" />
{$lang->recaptcha_target_first_time_only}
</label>
<label for="target_frequency_2" class="x_inline">
<input type="radio" id="target_frequency_2" name="target_frequency" value="every_time" checked="checked"|cond="$config->captcha->target_frequency === 'every_time'" />
{$lang->recaptcha_target_every_time}
</label>
</div>
</div>
<div class="x_clearfix btnArea">
<div class="x_pull-right">
<button type="submit" class="x_btn x_btn-primary">{$lang->cmd_save}</button>
</div>
</div>
</form>
</section>
<include target="./footer.html" />

View file

@ -1,10 +1,5 @@
<include target="./header.html" />
<section>
<ul class="x_nav x_nav-tabs">
<li class="x_active"><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedIPList')}">{$lang->cmd_denied_ip}</a></li>
<li><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedWordList')}">{$lang->cmd_denied_word}</a></li>
<li><a href="{getUrl('','module','admin','act','dispSpamfilterAdminConfigBlock')}">{$lang->cmd_config_block}</a></li>
</ul>
<form action="./" method="post">
<input type="hidden" name="act" value="procSpamfilterAdminDeleteDeniedIP" />
<input type="hidden" name="module" value="spamfilter" />

View file

@ -1,10 +1,5 @@
<include target="./header.html" />
<section>
<ul class="x_nav x_nav-tabs">
<li><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedIPList')}">{$lang->cmd_denied_ip}</a></li>
<li class="x_active"><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedWordList')}">{$lang->cmd_denied_word}</a></li>
<li><a href="{getUrl('','module','admin','act','dispSpamfilterAdminConfigBlock')}">{$lang->cmd_config_block}</a></li>
</ul>
<form action="./" method="post">
<input type="hidden" name="act" value="procSpamfilterAdminDeleteDeniedWord" />
<input type="hidden" name="module" value="spamfilter" />

View file

@ -6,3 +6,9 @@
<div cond="$XE_VALIDATOR_MESSAGE && $XE_VALIDATOR_ID == 'modules/spamfilter/tpl/1'" class="message {$XE_VALIDATOR_MESSAGE_TYPE}">
<p>{$XE_VALIDATOR_MESSAGE}</p>
</div>
<ul class="x_nav x_nav-tabs">
<li class="x_active"|cond="$act === 'dispSpamfilterAdminDeniedIPList'"><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedIPList')}">{$lang->cmd_denied_ip}</a></li>
<li class="x_active"|cond="$act === 'dispSpamfilterAdminDeniedWordList'"><a href="{getUrl('','module','admin','act','dispSpamfilterAdminDeniedWordList')}">{$lang->cmd_denied_word}</a></li>
<li class="x_active"|cond="$act === 'dispSpamfilterAdminConfigBlock'"><a href="{getUrl('','module','admin','act','dispSpamfilterAdminConfigBlock')}">{$lang->cmd_config_block}</a></li>
<li class="x_active"|cond="$act === 'dispSpamfilterAdminConfigCaptcha'"><a href="{getUrl('','module','admin','act','dispSpamfilterAdminConfigCaptcha')}">{$lang->cmd_captcha_config}</a></li>
</ul>

View file

@ -0,0 +1,40 @@
function reCaptchaCallback() {
var recaptcha_config = $("#recaptcha-config");
var recaptcha_instances = $(".g-recaptcha");
var recaptcha_instance_id = 1;
if (recaptcha_instances.size() === 0) {
var autoinsert_candidates = $("form").filter(function() {
var actinput = $("input[name='act']", this);
if (actinput.size() && actinput.val() && actinput.val().match(/^proc.+(Insert(Document|Comment|)|Login|FindAccount|ResendAuthMail)/i)) {
return true;
}
var procfilter = $(this).attr("onsubmit");
if (procfilter && procfilter.match(/procFilter\b.+\binsert/i)) {
return true;
}
return false;
});
autoinsert_candidates.each(function() {
var new_instance = $('<div class="g-recaptcha"></div>');
new_instance.attr("id", "recaptcha-instance-" + recaptcha_instance_id++);
var autoinsert_point = $(this).find("button[type='submit'],input[type='submit']").parent();
if (autoinsert_point.size()) {
new_instance.insertBefore(autoinsert_point);
} else {
new_instance.appendTo($(this));
}
});
var recaptcha_instances = $(".g-recaptcha");
}
recaptcha_instances.each(function() {
var instance = $(this);
grecaptcha.render(instance.attr("id"), {
sitekey: recaptcha_config.data("sitekey"),
size: recaptcha_config.data("size"),
theme: recaptcha_config.data("theme")
});
});
}