/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2011-2012 Eugene Fradkin (eugene.fradkin@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ext.mysql.editors;
import org.jkiss.dbeaver.Log;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.ext.mysql.MySQLMessages;
import org.jkiss.dbeaver.ext.mysql.controls.PrivilegeTableControl;
import org.jkiss.dbeaver.ext.mysql.edit.MySQLCommandGrantPrivilege;
import org.jkiss.dbeaver.ext.mysql.model.*;
import org.jkiss.dbeaver.model.edit.DBECommandReflector;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.load.DatabaseLoadService;
import org.jkiss.dbeaver.model.DBIcon;
import org.jkiss.dbeaver.ui.DBeaverIcons;
import org.jkiss.dbeaver.ui.LoadingJob;
import org.jkiss.dbeaver.ui.UIUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.List;
/**
* MySQLUserEditorPrivileges
*/
public class MySQLUserEditorPrivileges extends MySQLUserEditorAbstract
{
private static final Log log = Log.getLog(MySQLUserEditorPrivileges.class);
private PageControl pageControl;
private Table catalogsTable;
private Table tablesTable;
private boolean isLoaded = false;
private MySQLCatalog selectedCatalog;
private MySQLTableBase selectedTable;
private PrivilegeTableControl tablePrivilegesTable;
private PrivilegeTableControl otherPrivilegesTable;
private volatile List<MySQLGrant> grants;
private Font boldFont;
@Override
public void createPartControl(Composite parent)
{
boldFont = UIUtils.makeBoldFont(parent.getFont());
pageControl = new PageControl(parent);
Composite container = UIUtils.createPlaceholder(pageControl, 2, 5);
GridData gd = new GridData(GridData.FILL_BOTH);
container.setLayoutData(gd);
Composite leftPane = UIUtils.createPlaceholder(container, 2);
leftPane.setLayoutData(new GridData(GridData.FILL_BOTH));
leftPane.setLayout(new GridLayout(2, true));
{
Composite catalogGroup = UIUtils.createControlGroup(leftPane, MySQLMessages.editors_user_editor_privileges_group_catalogs, 1, GridData.FILL_BOTH, 0);
catalogsTable = new Table(catalogGroup, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL);
catalogsTable.setHeaderVisible(true);
gd = new GridData(GridData.FILL_BOTH);
catalogsTable.setLayoutData(gd);
catalogsTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int selIndex = catalogsTable.getSelectionIndex();
if (selIndex <= 0) {
selectedCatalog = null;
} else {
selectedCatalog = (MySQLCatalog) catalogsTable.getItem(selIndex).getData();
}
showCatalogTables();
showGrants();
}
});
UIUtils.createTableColumn(catalogsTable, SWT.LEFT, MySQLMessages.editors_user_editor_privileges_column_catalog);
{
TableItem item = new TableItem(catalogsTable, SWT.NONE);
item.setText("% (All)"); //$NON-NLS-1$
item.setImage(DBeaverIcons.getImage(DBIcon.TREE_DATABASE));
}
for (MySQLCatalog catalog : getDatabaseObject().getDataSource().getCatalogs()) {
TableItem item = new TableItem(catalogsTable, SWT.NONE);
item.setText(catalog.getName());
item.setImage(DBeaverIcons.getImage(DBIcon.TREE_DATABASE));
item.setData(catalog);
}
UIUtils.packColumns(catalogsTable);
}
{
Composite tablesGroup = UIUtils.createControlGroup(leftPane, MySQLMessages.editors_user_editor_privileges_group_tables, 1, GridData.FILL_BOTH, 0);
tablesTable = new Table(tablesGroup, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL);
tablesTable.setHeaderVisible(true);
gd = new GridData(GridData.FILL_BOTH);
tablesTable.setLayoutData(gd);
tablesTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int selIndex = tablesTable.getSelectionIndex();
if (selIndex <= 0) {
selectedTable = null;
} else {
selectedTable = (MySQLTableBase) tablesTable.getItem(selIndex).getData();
}
showGrants();
}
});
UIUtils.createTableColumn(tablesTable, SWT.LEFT, MySQLMessages.editors_user_editor_privileges_column_table);
UIUtils.packColumns(tablesTable);
}
Composite ph = UIUtils.createPlaceholder(container, 1);
ph.setLayoutData(new GridData(GridData.FILL_BOTH));
tablePrivilegesTable = new PrivilegeTableControl(ph, MySQLMessages.editors_user_editor_privileges_control_table_privileges);
gd = new GridData(GridData.FILL_BOTH);
tablePrivilegesTable.setLayoutData(gd);
otherPrivilegesTable = new PrivilegeTableControl(ph, MySQLMessages.editors_user_editor_privileges_control_other_privileges);
gd = new GridData(GridData.FILL_BOTH);
otherPrivilegesTable.setLayoutData(gd);
catalogsTable.setSelection(0);
showCatalogTables();
pageControl.createProgressPanel();
parent.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e)
{
UIUtils.dispose(boldFont);
}
});
addGrantListener(tablePrivilegesTable);
addGrantListener(otherPrivilegesTable);
}
private void addGrantListener(final PrivilegeTableControl privTable)
{
privTable.addListener(SWT.Modify, new Listener() {
@Override
public void handleEvent(Event event)
{
final MySQLPrivilege privilege = (MySQLPrivilege) event.data;
final boolean isGrant = event.detail == 1;
final MySQLCatalog curCatalog = selectedCatalog;
final MySQLTableBase curTable = selectedTable;
updateLocalData(privilege, isGrant, curCatalog, curTable);
// Add command
addChangeCommand(
new MySQLCommandGrantPrivilege(
getDatabaseObject(),
isGrant,
curCatalog,
curTable,
privilege),
new DBECommandReflector<MySQLUser, MySQLCommandGrantPrivilege>() {
@Override
public void redoCommand(MySQLCommandGrantPrivilege mySQLCommandGrantPrivilege)
{
if (!privTable.isDisposed() && curCatalog == selectedCatalog && curTable == selectedTable) {
privTable.checkPrivilege(privilege, isGrant);
}
updateLocalData(privilege, isGrant, curCatalog, curTable);
}
@Override
public void undoCommand(MySQLCommandGrantPrivilege mySQLCommandGrantPrivilege)
{
if (!privTable.isDisposed() && curCatalog == selectedCatalog && curTable == selectedTable) {
privTable.checkPrivilege(privilege, !isGrant);
}
updateLocalData(privilege, !isGrant, curCatalog, curTable);
}
});
}
});
}
private void updateLocalData(MySQLPrivilege privilege, boolean isGrant, MySQLCatalog curCatalog, MySQLTableBase curTable)
{
// Modify local grants (and clear grants cache in user objects)
getDatabaseObject().clearGrantsCache();
boolean found = false;
for (MySQLGrant grant : grants) {
if (grant.matches(curCatalog) && grant.matches(curTable)) {
if (privilege.isGrantOption()) {
grant.setGrantOption(isGrant);
} else if (isGrant) {
if (!grant.getPrivileges().contains(privilege)) {
grant.addPrivilege(privilege);
}
} else {
grant.removePrivilege(privilege);
}
found = true;
break;
}
}
if (!found) {
List<MySQLPrivilege> privileges = new ArrayList<>();
if (!privilege.isGrantOption()) {
privileges.add(privilege);
}
MySQLGrant grant = new MySQLGrant(
getDatabaseObject(),
privileges,
curCatalog == null ? "*" : curCatalog.getName(), //$NON-NLS-1$
curTable == null ? "*" : curTable.getName(), //$NON-NLS-1$
false,
privilege.isGrantOption());
grants.add(grant);
}
highlightCatalogs();
highlightTables();
}
private void showCatalogTables()
{
LoadingJob.createService(
new DatabaseLoadService<Collection<MySQLTableBase>>(MySQLMessages.editors_user_editor_privileges_service_load_tables, getExecutionContext()) {
@Override
public Collection<MySQLTableBase> evaluate(DBRProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
if (selectedCatalog == null) {
return Collections.emptyList();
}
try {
return selectedCatalog.getTableCache().getAllObjects(monitor, selectedCatalog);
} catch (DBException e) {
log.error(e);
}
return null;
}
},
pageControl.createTablesLoadVisualizer())
.schedule();
}
private void showGrants()
{
if (grants == null) {
return;
}
List<MySQLGrant> curGrants = new ArrayList<>();
for (MySQLGrant grant : grants) {
if (grant.matches(selectedCatalog) && grant.matches(selectedTable)) {
curGrants.add(grant);
}
}
tablePrivilegesTable.fillGrants(curGrants);
otherPrivilegesTable.fillGrants(curGrants);
}
@Override
public synchronized void activatePart()
{
if (isLoaded) {
return;
}
isLoaded = true;
LoadingJob.createService(
new DatabaseLoadService<java.util.List<MySQLPrivilege>>(MySQLMessages.editors_user_editor_privileges_service_load_privileges, getExecutionContext()) {
@Override
public java.util.List<MySQLPrivilege> evaluate(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
return getDatabaseObject().getDataSource().getPrivileges(monitor);
} catch (DBException e) {
throw new InvocationTargetException(e);
}
}
},
pageControl.createPrivilegesLoadVisualizer())
.schedule();
}
@Override
protected PageControl getPageControl()
{
return pageControl;
}
@Override
protected void processGrants(List<MySQLGrant> grantsTmp)
{
this.grants = new ArrayList<>(grantsTmp);
for (Iterator<MySQLGrant> i = grants.iterator(); i.hasNext();) {
MySQLGrant grant = i.next();
if (!grant.isAllPrivileges() && !grant.hasNonAdminPrivileges()) {
i.remove();
}
}
highlightCatalogs();
showGrants();
showCatalogTables();
}
private void highlightCatalogs()
{
// Highlight granted catalogs
if (catalogsTable != null && !catalogsTable.isDisposed()) {
for (TableItem item : catalogsTable.getItems()) {
MySQLCatalog catalog = (MySQLCatalog)item.getData();
item.setFont(null);
if (grants != null) {
for (MySQLGrant grant : grants) {
if (grant.matches(catalog) && !grant.isEmpty()) {
item.setFont(boldFont);
break;
}
}
}
}
}
}
private void highlightTables()
{
if (tablesTable != null && !tablesTable.isDisposed()) {
for (TableItem item : tablesTable.getItems()) {
MySQLTableBase table = (MySQLTableBase) item.getData();
item.setFont(null);
if (grants != null) {
for (MySQLGrant grant : grants) {
if (grant.matches(selectedCatalog) && grant.matches(table) && !grant.isEmpty()) {
item.setFont(boldFont);
break;
}
}
}
}
}
}
@Override
public void refreshPart(Object source, boolean force)
{
// do nothing
}
private class PageControl extends UserPageControl {
public PageControl(Composite parent) {
super(parent);
}
public ProgressVisualizer<Collection<MySQLTableBase>> createTablesLoadVisualizer() {
return new ProgressVisualizer<Collection<MySQLTableBase>>() {
@Override
public void completeLoading(Collection<MySQLTableBase> tables) {
super.completeLoading(tables);
if (tablesTable.isDisposed()) {
return;
}
tablesTable.removeAll();
{
TableItem item = new TableItem(tablesTable, SWT.NONE);
item.setText("% (All)"); //$NON-NLS-1$
item.setImage(DBeaverIcons.getImage(DBIcon.TREE_TABLE));
}
for (MySQLTableBase table : tables) {
TableItem item = new TableItem(tablesTable, SWT.NONE);
item.setText(table.getName());
item.setImage(DBeaverIcons.getImage(table.isView() ? DBIcon.TREE_VIEW : DBIcon.TREE_TABLE));
item.setData(table);
}
highlightTables();
UIUtils.packColumns(tablesTable);
}
};
}
public ProgressVisualizer<java.util.List<MySQLPrivilege>> createPrivilegesLoadVisualizer() {
return new ProgressVisualizer<java.util.List<MySQLPrivilege>>() {
@Override
public void completeLoading(java.util.List<MySQLPrivilege> privs) {
super.completeLoading(privs);
List<MySQLPrivilege> otherPrivs = new ArrayList<>();
List<MySQLPrivilege> tablePrivs = new ArrayList<>();
for (MySQLPrivilege priv : privs) {
if (priv.getKind() == MySQLPrivilege.Kind.ADMIN) {
continue;
}
if (priv.getContext().contains("Table")) {
tablePrivs.add(priv);
} else {
otherPrivs.add(priv);
}
}
tablePrivilegesTable.fillPrivileges(tablePrivs);
otherPrivilegesTable.fillPrivileges(otherPrivs);
loadGrants();
}
};
}
}
}