Extract HTML from table specific privileges

Server\Privileges::getHtmlForTableSpecificPrivileges

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
Maurício Meneghini Fauth 2019-08-28 00:51:35 -03:00
parent 449eae8e35
commit d3fb94a674
4 changed files with 169 additions and 311 deletions

View File

@ -504,40 +504,6 @@ class Privileges
];
}
/**
* Displays on which column(s) a table-specific privilege is granted
*
* @param array $columns columns array
* @param array $row first row from result or boolean false
* @param string $name_for_select privilege types - Select_priv, Insert_priv
* Update_priv, References_priv
* @param string $priv_for_header privilege for header
* @param string $name privilege name: insert, select, update, references
* @param string $name_for_dfn name for dfn
* @param string $name_for_current name for current
*
* @return string html snippet
*/
public function getHtmlForColumnPrivileges(
array $columns,
array $row,
$name_for_select,
$priv_for_header,
$name,
$name_for_dfn,
$name_for_current
) {
return $this->template->render('server/privileges/column_privileges', [
'columns' => $columns,
'row' => $row,
'name_for_select' => $name_for_select,
'priv_for_header' => $priv_for_header,
'name' => $name,
'name_for_dfn' => $name_for_dfn,
'name_for_current' => $name_for_current,
]);
}
/**
* Get sql query for display privileges table
*
@ -1064,165 +1030,60 @@ class Privileges
}
}
$this->dbi->freeResult($res);
unset($res, $row1, $current);
$html_output = '<input type="hidden" name="grant_count" '
. 'value="' . count($row) . '">' . "\n"
. '<input type="hidden" name="column_count" '
. 'value="' . count($columns) . '">' . "\n"
. '<fieldset id="fieldset_user_priv">' . "\n"
. '<legend data-submenu-label="' . __('Table') . '">' . __('Table-specific privileges')
. '</legend>'
. '<p><small><i>'
. __('Note: MySQL privilege names are expressed in English.')
. '</i></small></p>';
$notAttachedPrivileges = $this->getNotAttachedPrivilegesToTableSpecificColumn($row);
// privs that are attached to a specific column
$html_output .= $this->getHtmlForAttachedPrivilegesToTableSpecificColumn(
$columns,
$row
);
// privs that are not attached to a specific column
$html_output .= '<div class="item">' . "\n"
. $this->getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
. '</div>' . "\n";
// for Safari 2.0.2
$html_output .= '<div class="clearfloat"></div>' . "\n";
return $html_output;
return $this->template->render('server/privileges/table_specific_privileges', [
'row' => $row,
'columns' => $columns,
'privileges' => $notAttachedPrivileges,
]);
}
/**
* Get HTML snippet for privileges that are attached to a specific column
*
* @param array $columns columns array
* @param array $row first row from result or boolean false
*
* @return string
*/
public function getHtmlForAttachedPrivilegesToTableSpecificColumn(array $columns, array $row)
{
$html_output = $this->getHtmlForColumnPrivileges(
$columns,
$row,
'Select_priv',
'SELECT',
'select',
__('Allows reading data.'),
'Select'
);
$html_output .= $this->getHtmlForColumnPrivileges(
$columns,
$row,
'Insert_priv',
'INSERT',
'insert',
__('Allows inserting and replacing data.'),
'Insert'
);
$html_output .= $this->getHtmlForColumnPrivileges(
$columns,
$row,
'Update_priv',
'UPDATE',
'update',
__('Allows changing data.'),
'Update'
);
$html_output .= $this->getHtmlForColumnPrivileges(
$columns,
$row,
'References_priv',
'REFERENCES',
'references',
__('Has no effect in this MySQL version.'),
'References'
);
return $html_output;
}
/**
* Get HTML for privileges that are not attached to a specific column
* Get privileges that are not attached to a specific column
*
* @param array $row first row from result or boolean false
*
* @return string
* @return array
*/
public function getHtmlForNotAttachedPrivilegesToTableSpecificColumn(array $row)
private function getNotAttachedPrivilegesToTableSpecificColumn(array $row): array
{
$html_output = '';
foreach ($row as $current_grant => $current_grant_value) {
$grant_type = substr($current_grant, 0, -5);
if (in_array($grant_type, ['Select', 'Insert', 'Update', 'References'])
) {
$privileges = [];
foreach ($row as $grant => $value) {
$type = substr($grant, 0, -5);
if (in_array($type, ['Select', 'Insert', 'Update', 'References'])) {
continue;
}
// make a substitution to match the messages variables;
// also we must substitute the grant we get, because we can't generate
// a form variable containing blanks (those would get changed to
// an underscore when receiving the POST)
if ($current_grant == 'Create View_priv') {
$tmp_current_grant = 'CreateView_priv';
$current_grant = 'Create_view_priv';
} elseif ($current_grant == 'Show view_priv') {
$tmp_current_grant = 'ShowView_priv';
$current_grant = 'Show_view_priv';
} elseif ($current_grant == 'Delete versioning rows_priv') {
$tmp_current_grant = 'DeleteHistoricalRows_priv';
$current_grant = 'Delete_history_priv';
/**
* Make a substitution to match the messages variables;
* also we must substitute the grant we get, because we can't generate
* a form variable containing blanks (those would get changed to
* an underscore when receiving the POST).
*/
if ($grant === 'Create View_priv') {
$grantName = 'CreateView_priv';
$grant = 'Create_view_priv';
} elseif ($grant === 'Show view_priv') {
$grantName = 'ShowView_priv';
$grant = 'Show_view_priv';
} elseif ($grant === 'Delete versioning rows_priv') {
$grantName = 'DeleteHistoricalRows_priv';
$grant = 'Delete_history_priv';
} else {
$tmp_current_grant = $current_grant;
$grantName = $grant;
}
$descriptionName = 'strPrivDesc' . mb_substr($grantName, 0, -5);
$html_output .= '<div class="item">' . "\n"
. '<input type="checkbox"'
. ' name="' . $current_grant . '" id="checkbox_' . $current_grant
. '" value="Y" '
. ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
. 'title="';
$privGlobalName = 'strPrivDesc'
. mb_substr(
$tmp_current_grant,
0,
mb_strlen($tmp_current_grant) - 5
);
$html_output .= (isset($GLOBALS[$privGlobalName])
? $GLOBALS[$privGlobalName]
: $GLOBALS[$privGlobalName . 'Tbl']
)
. '">' . "\n";
$privGlobalName1 = 'strPrivDesc'
. mb_substr(
$tmp_current_grant,
0,
- 5
);
$html_output .= '<label for="checkbox_' . $current_grant
. '"><code><dfn title="'
. (isset($GLOBALS[$privGlobalName1])
? $GLOBALS[$privGlobalName1]
: $GLOBALS[$privGlobalName1 . 'Tbl']
)
. '">'
. mb_strtoupper(
mb_substr(
$current_grant,
0,
-5
)
)
. '</dfn></code></label>' . "\n"
. '</div>' . "\n";
} // end foreach ()
return $html_output;
$privileges[] = [
'grant' => $grant,
'is_checked' => $value === 'Y',
'name' => mb_strtoupper(mb_substr($grant, 0, -5)),
'description' => $GLOBALS[$descriptionName] ?? $GLOBALS[$descriptionName . 'Tbl'] ?? '',
];
}
return $privileges;
}
/**

View File

@ -1,24 +0,0 @@
<div class="item" id="div_item_{{ name }}">
<label for="select_{{ name }}_priv">
<code><dfn title="{{ name_for_dfn }}">{{ priv_for_header }}</dfn></code>
</label>
<select id="select_{{ name }}_priv" name="{{ name_for_select }}[]" multiple="multiple" size="8">
{% for curr_col, curr_col_privs in columns %}
<option value="{{ curr_col }}"
{% if row[name_for_select] == 'Y' or curr_col_privs[name_for_current] %}
selected="selected"
{% endif %}>
{{ curr_col }}
</option>
{% endfor %}
</select>
<em>{% trans 'Or' %}</em>
<label for="checkbox_{{ name_for_select }}_none">
<input type="checkbox" name="{{ name_for_select }}_none"
id="checkbox_{{ name_for_select }}_none"
title="{% trans %}None{% context %}None privileges{% endtrans %}">
{% trans %}None{% context %}None privileges{% endtrans %}
</label>
</div>

View File

@ -0,0 +1,106 @@
<input type="hidden" name="grant_count" value="{{ row|length }}">
<input type="hidden" name="column_count" value="{{ columns|length }}">
<fieldset id="fieldset_user_priv">
<legend data-submenu-label="{% trans 'Table' %}">
{% trans 'Table-specific privileges' %}
</legend>
<p>
<small><em>{% trans 'Note: MySQL privilege names are expressed in English.' %}</em></small>
</p>
<div class="item" id="div_item_select">
<label for="select_select_priv">
<code><dfn title="{% trans 'Allows reading data.' %}">SELECT</dfn></code>
</label>
<select id="select_select_priv" name="Select_priv[]" size="8" multiple>
{% for curr_col, curr_col_privs in columns %}
<option value="{{ curr_col }}"{{ row['Select_priv'] == 'Y' or curr_col_privs['Select'] ? ' selected' }}>
{{ curr_col }}
</option>
{% endfor %}
</select>
<em>{% trans 'Or' %}</em>
<label for="checkbox_Select_priv_none">
<input type="checkbox" name="Select_priv_none" id="checkbox_Select_priv_none" title="
{%- trans %}None{% context %}None privileges{% endtrans %}">
{% trans %}None{% context %}None privileges{% endtrans %}
</label>
</div>
<div class="item" id="div_item_insert">
<label for="select_insert_priv">
<code><dfn title="{% trans 'Allows inserting and replacing data.' %}">INSERT</dfn></code>
</label>
<select id="select_insert_priv" name="Insert_priv[]" size="8" multiple>
{% for curr_col, curr_col_privs in columns %}
<option value="{{ curr_col }}"{{ row['Insert_priv'] == 'Y' or curr_col_privs['Insert'] ? ' selected' }}>
{{ curr_col }}
</option>
{% endfor %}
</select>
<em>{% trans 'Or' %}</em>
<label for="checkbox_Insert_priv_none">
<input type="checkbox" name="Insert_priv_none" id="checkbox_Insert_priv_none" title="
{%- trans %}None{% context %}None privileges{% endtrans %}">
{% trans %}None{% context %}None privileges{% endtrans %}
</label>
</div>
<div class="item" id="div_item_update">
<label for="select_update_priv">
<code><dfn title="{% trans 'Allows changing data.' %}">UPDATE</dfn></code>
</label>
<select id="select_update_priv" name="Update_priv[]" size="8" multiple>
{% for curr_col, curr_col_privs in columns %}
<option value="{{ curr_col }}"{{ row['Update_priv'] == 'Y' or curr_col_privs['Update'] ? ' selected' }}>
{{ curr_col }}
</option>
{% endfor %}
</select>
<em>{% trans 'Or' %}</em>
<label for="checkbox_Update_priv_none">
<input type="checkbox" name="Update_priv_none" id="checkbox_Update_priv_none" title="
{%- trans %}None{% context %}None privileges{% endtrans %}">
{% trans %}None{% context %}None privileges{% endtrans %}
</label>
</div>
<div class="item" id="div_item_references">
<label for="select_references_priv">
<code><dfn title="{% trans 'Has no effect in this MySQL version.' %}">REFERENCES</dfn></code>
</label>
<select id="select_references_priv" name="References_priv[]" size="8" multiple>
{% for curr_col, curr_col_privs in columns %}
<option value="{{ curr_col }}"{{ row['References_priv'] == 'Y' or curr_col_privs['References'] ? ' selected' }}>
{{ curr_col }}
</option>
{% endfor %}
</select>
<em>{% trans 'Or' %}</em>
<label for="checkbox_References_priv_none">
<input type="checkbox" name="References_priv_none" id="checkbox_References_priv_none" title="
{%- trans %}None{% context %}None privileges{% endtrans %}">
{% trans %}None{% context %}None privileges{% endtrans %}
</label>
</div>
<div class="item">
{% for privilege in privileges %}
<div class="item">
<input type="checkbox" name="{{ privilege.grant }}" id="checkbox_{{ privilege.grant }}" value="Y" title="{{ privilege.description }}"{{ privilege.is_checked ? ' checked' }}>
<label for="checkbox_{{ privilege.grant }}">
<code><dfn title="{{ privilege.description }}">{{ privilege.name }}</dfn></code>
</label>
</div>
{% endfor %}
</div>
<div class="clearfloat"></div>

View File

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Server;
use PhpMyAdmin\Config;
use PhpMyAdmin\Core;
use PhpMyAdmin\Relation;
use PhpMyAdmin\RelationCleanup;
@ -40,50 +41,17 @@ class PrivilegesTest extends TestCase
*/
protected function setUp(): void
{
//Constants
if (! defined("PMA_USR_BROWSER_AGENT")) {
define("PMA_USR_BROWSER_AGENT", "other");
}
//$_REQUEST
$_REQUEST['log'] = "index1";
$_REQUEST['pos'] = 3;
$_GET['initial'] = null;
//$GLOBALS
$GLOBALS['lang'] = 'en';
$GLOBALS['cfg']['MaxRows'] = 10;
$GLOBALS['cfg']['SendErrorReports'] = "never";
$GLOBALS['cfg']['ServerDefault'] = "server";
$GLOBALS['cfg']['RememberSorting'] = true;
$GLOBALS['cfg']['SQP'] = [];
$GLOBALS['cfg']['MaxCharactersInDisplayedSQL'] = 1000;
$GLOBALS['cfg']['ShowSQL'] = true;
$GLOBALS['cfg']['TableNavigationLinksMode'] = 'icons';
$GLOBALS['cfg']['LimitChars'] = 100;
$GLOBALS['cfg']['AllowThirdPartyFraming'] = false;
$GLOBALS['cfg']['ActionLinksMode'] = "both";
$GLOBALS['cfg']['DefaultTabDatabase'] = 'structure';
$GLOBALS['cfg']['DefaultTabTable'] = "structure";
$GLOBALS['cfg']['NavigationTreeDefaultTabTable'] = "structure";
$GLOBALS['cfg']['NavigationTreeDefaultTabTable2'] = "";
$GLOBALS['cfg']['Confirm'] = "Confirm";
$GLOBALS['cfg']['ShowHint'] = true;
$GLOBALS['cfg']['ShowDatabasesNavigationAsTree'] = true;
$GLOBALS['cfg']['LoginCookieValidity'] = 1440;
$GLOBALS['cfg']['enable_drag_drop_import'] = true;
$GLOBALS['PMA_Config'] = new Config();
$GLOBALS['PMA_Config']->enableBc();
$GLOBALS['cfg']['Server']['DisableIS'] = false;
$GLOBALS['cfgRelation'] = [];
$GLOBALS['cfgRelation']['menuswork'] = false;
$GLOBALS['table'] = "table";
$GLOBALS['PMA_PHP_SELF'] = Core::getenv('PHP_SELF');
$GLOBALS['pmaThemeImage'] = 'image';
$GLOBALS['server'] = 1;
$GLOBALS['db'] = 'db';
$GLOBALS['hostname'] = "hostname";
$GLOBALS['username'] = "username";
$GLOBALS['text_dir'] = "text_dir";
$GLOBALS['is_reload_priv'] = true;
$relation = new Relation($GLOBALS['dbi']);
$this->serverPrivileges = new Privileges(
@ -332,66 +300,6 @@ class PrivilegesTest extends TestCase
);
}
/**
* Test for getHtmlForColumnPrivileges
*
* @return void
*/
public function testGetHtmlForColumnPrivileges()
{
$columns = [
'row1' => 'name1',
];
$row = [
'name_for_select' => 'Y',
];
$name_for_select = 'name_for_select';
$priv_for_header = 'priv_for_header';
$name = 'name';
$name_for_dfn = 'name_for_dfn';
$name_for_current = 'name_for_current';
$html = $this->serverPrivileges->getHtmlForColumnPrivileges(
$columns,
$row,
$name_for_select,
$priv_for_header,
$name,
$name_for_dfn,
$name_for_current
);
//$name
$this->assertStringContainsString(
$name,
$html
);
//$name_for_dfn
$this->assertStringContainsString(
$name_for_dfn,
$html
);
//$priv_for_header
$this->assertStringContainsString(
$priv_for_header,
$html
);
//$name_for_select
$this->assertStringContainsString(
$name_for_select,
$html
);
//$columns and $row
$this->assertStringContainsString(
htmlspecialchars('row1'),
$html
);
//$columns and $row
$this->assertStringContainsString(
_pgettext('None privileges', 'None'),
$html
);
}
/**
* Test for getHtmlForRequires
*
@ -1320,13 +1228,16 @@ class PrivilegesTest extends TestCase
$row
);
//validate 1: getHtmlForAttachedPrivilegesToTableSpecificColumn
$item = $this->serverPrivileges->getHtmlForAttachedPrivilegesToTableSpecificColumn(
$columns,
$row
$this->assertStringContainsString(
'checkbox_Update_priv_none',
$html
);
$this->assertStringContainsString(
$item,
'<dfn title="Allows changing data.">UPDATE</dfn>',
$html
);
$this->assertStringContainsString(
'checkbox_Insert_priv_none',
$html
);
$this->assertStringContainsString(
@ -1346,12 +1257,12 @@ class PrivilegesTest extends TestCase
$html
);
//validate 2: getHtmlForNotAttachedPrivilegesToTableSpecificColumn
$item = $this->serverPrivileges->getHtmlForNotAttachedPrivilegesToTableSpecificColumn(
$row
$this->assertStringContainsString(
'title="strPrivDescShowViewTbl" checked>',
$html
);
$this->assertStringContainsString(
$item,
'<dfn title="strPrivDescCreate_viewTbl">CREATE_VIEW</dfn>',
$html
);
$this->assertStringContainsString(
@ -1362,6 +1273,10 @@ class PrivilegesTest extends TestCase
'ShowView_priv',
$html
);
$this->assertStringContainsString(
_pgettext('None privileges', 'None'),
$html
);
}
/**
@ -2563,13 +2478,13 @@ class PrivilegesTest extends TestCase
$this->assertStringContainsString('<td>A</td>', $actual);
$this->assertStringContainsString('<td>Z</td>', $actual);
$this->assertStringContainsString(
'<a class="ajax" href="index.php?route=/server/privileges&amp;initial=-&amp;'
. 'server=1&amp;lang=en">-</a>',
'<a class="ajax" href="index.php?route=/server/privileges&amp;initial=-'
. '&amp;lang=en">-</a>',
$actual
);
$this->assertStringContainsString(
'<a class="ajax" href="index.php?route=/server/privileges&amp;initial=%22&amp;'
. 'server=1&amp;lang=en">"</a>',
'<a class="ajax" href="index.php?route=/server/privileges&amp;initial=%22'
. '&amp;lang=en">"</a>',
$actual
);
$this->assertStringContainsString('Show all', $actual);