package org.basex.gui.dialog; import static org.basex.core.Text.*; import java.awt.BorderLayout; import java.awt.Dimension; import java.io.IOException; import javax.swing.JScrollPane; import org.basex.core.Commands.CmdPerm; import org.basex.core.cmd.AlterUser; import org.basex.core.cmd.CreateUser; import org.basex.core.cmd.DropUser; import org.basex.core.cmd.Grant; import org.basex.core.cmd.List; import org.basex.core.cmd.ShowUsers; import org.basex.gui.GUIConstants.Msg; import org.basex.gui.layout.BaseXBack; import org.basex.gui.layout.BaseXButton; import org.basex.gui.layout.BaseXCombo; import org.basex.gui.layout.BaseXLabel; import org.basex.gui.layout.BaseXLayout; import org.basex.gui.layout.BaseXPassword; import org.basex.gui.layout.BaseXTable; import org.basex.gui.layout.BaseXTextField; import org.basex.gui.layout.TableLayout; import org.basex.server.Session; import org.basex.util.Table; import org.basex.util.Token; import org.basex.util.Util; import org.basex.util.list.StringList; import org.basex.util.list.TokenList; /** * Panel for displaying information about global/local users. * * @author BaseX Team 2005-12, BSD License * @author Andreas Weiler */ final class DialogUser extends BaseXBack { /** Session. */ private Session sess; /** Global user table. */ private Table users = new Table(); /** Create button. */ private final BaseXButton create; /** Alter button. */ private final BaseXButton alter; /** Delete button. */ private final BaseXButton drop; /** Add button. */ private final BaseXButton add; /** Username textfield. */ private final BaseXTextField user; /** Password textfield. */ private final BaseXPassword pass; /** User columns. */ private final BaseXCombo addUser; /** Databases. */ private final BaseXCombo databases; /** User table. */ private final BaseXTable table; /** Info label. */ private final BaseXLabel info; /** Flag global/local. */ private final boolean global; /** Dialog. */ private final DialogServer dia; /** Table panel. */ private final BaseXBack tablePanel; /** * Constructor. * @param g global/local flag * @param d dialog window */ DialogUser(final boolean g, final DialogServer d) { global = g; dia = d; layout(new TableLayout(7, 1, 0, 4)).border(8); user = new BaseXTextField("", dia); user.addKeyListener(dia.keys); BaseXLayout.setWidth(user, 100); create = new BaseXButton(CREATE, dia); pass = new BaseXPassword(dia.gui); pass.addKeyListener(dia.keys); BaseXLayout.setWidth(pass, 100); alter = new BaseXButton(S_ALTER, dia); drop = new BaseXButton(DROP + DOTS, dia); info = new BaseXLabel(" "); add(new BaseXLabel(S_CREATEU + COLS, false, true)); BaseXBack p = new BaseXBack(new TableLayout(1, 5, 8, 0)).border(0, 0, 6, 0); p.add(new BaseXLabel(USERNAME + COLS)); p.add(user); p.add(new BaseXLabel(PASSWORD + COLS)); p.add(pass); p.add(create); add(p); tablePanel = new BaseXBack(new BorderLayout(0, 5)); databases = new BaseXCombo(dia); BaseXLayout.setWidth(databases, 210); addUser = new BaseXCombo(dia); add = new BaseXButton(ADD, dia); BaseXLayout.setWidth(addUser, 131); if(!global) { p = new BaseXBack(new TableLayout(2, 3, 8, 2)); p.add(new BaseXLabel(DATABASES + COL, false, true)); p.add(new BaseXLabel(ADD + COL, false, true)); p.add(new BaseXLabel()); p.add(databases); p.add(addUser); p.add(add); tablePanel.add(p, BorderLayout.NORTH); } p = new BaseXBack(new TableLayout(2, 2, 8, 5)); p.add(new BaseXLabel(global ? S_GLOBPERM : S_LOCPERM, false, true)); p.add(new BaseXLabel()); table = new BaseXTable(users, dia); final JScrollPane sp = new JScrollPane(table); sp.setPreferredSize(new Dimension(350, 220)); p.add(sp); final BaseXBack pp = new BaseXBack(new TableLayout(2, 1, 0, 5)); if(global) pp.add(alter); pp.add(drop); p.add(pp); tablePanel.add(p, BorderLayout.CENTER); tablePanel.add(info, BorderLayout.SOUTH); add(tablePanel); action(null); } /** * Reacts on user input. * @param cmp calling component */ void action(final Object cmp) { boolean ok = true; String msg = null; try { final Object di = databases.getSelectedItem(); final String db = di == null ? null : di.toString(); if(cmp instanceof Object[]) { final Object[] o = (Object[]) cmp; final boolean g = o[0] == Boolean.TRUE; final CmdPerm perm = CmdPerm.values()[(Integer) o[2] - (g ? 0 : 1)]; final String uname = table.getModel().getValueAt( (Integer) o[1], 0).toString(); final boolean confirm = !g && uname.equals(dia.loguser.getText()); if(confirm && !Dialog.confirm(dia.gui, Util.info(S_DBREVOKE))) return; sess.execute(new Grant(perm, uname, db)); msg = sess.info(); if(confirm) { if(perm == CmdPerm.ADMIN) { dia.tabs.setSelectedIndex(0); dia.action(dia.disconnect); } else { setSess(sess); } } else { setData(); } } else if(cmp == this) { setSess(sess); } else if(cmp == databases) { setData(); } else if(cmp == create || cmp == user || cmp == pass) { final String u = user.getText(); final String p = Token.md5(new String(pass.getPassword())); sess.execute(new CreateUser(u, p)); msg = sess.info(); setData(); user.setText(""); pass.setText(""); user.requestFocusInWindow(); } else if(cmp == drop) { String msg2 = ""; final int[] rows = table.getSelectedRows(); if(Dialog.confirm(dia.gui, Util.info(S_DRQUESTION, rows.length))) { for(final int r : rows) { sess.execute(new DropUser(table.data.value(r, 0), db)); if(msg == null) msg = sess.info(); else if(msg2.isEmpty()) msg2 = " (...)"; if(!ok) break; } msg += msg2; setData(); } } else if(cmp == alter) { final DialogPass dp = new DialogPass(dia.gui); if(dp.ok()) { sess.execute(new AlterUser(table.getValueAt( table.getSelectedRow(), 0).toString(), Token.md5(dp.pass()))); msg = sess.info(); } } else if(cmp == add) { final String us = addUser.getSelectedItem().toString(); for(int r = 0; r < users.contents.size(); ++r) { if(!users.value(r, 0).equals(us)) continue; int c = 3; while(--c >= 0 && users.value(r, c).isEmpty()); final String perm = CmdPerm.values()[c].toString(); sess.execute(new Grant(perm, us, db)); msg = sess.info(); if(!ok) break; } setData(); addUser.requestFocusInWindow(); } } catch(final IOException ex) { msg = Util.message(ex); ok = false; } final boolean valname = user.getText().matches("[\\w]*"); final boolean valpass = new String(pass.getPassword()).matches("[^ ;'\"]*"); boolean newname = true; for(int r = 0; r < users.contents.size(); ++r) newname &= !users.value(r, 0).equals(user.getText()); alter.setEnabled(table.getSelectedRows().length == 1); create.setEnabled(valname && valpass && newname && !user.getText().isEmpty() && pass.getPassword().length != 0); add.setEnabled(addUser.getSelectedIndex() > 0); addUser.setEnabled(addUser.getSelectedIndex() > -1); boolean valdrop = true; for(final int r : table.getSelectedRows()) { valdrop &= !table.data.value(r, 0).equals(ADMIN); } drop.setEnabled(valdrop && table.getSelectedRows().length > 0); valdrop |= table.getSelectedRows().length == 1; Msg icon = ok ? Msg.SUCCESS : Msg.ERROR; if(msg == null && !(valname && valpass && newname && valdrop)) { msg = !newname ? Util.info(USER_EXISTS_X, user.getText()) : !valdrop ? ADMIN_STATIC_X : Util.info(INVALID_X, !valname ? USERNAME : PASSWORD); icon = Msg.WARN; } info.setText(msg, icon); } /** * Sets new data. * @throws IOException I/O exception */ void setData() throws IOException { users = table(null); if(global) { table.update(users); } else { addUser.removeAllItems(); final int i = databases.getSelectedIndex(); if(i == 0) table.update(new Table()); if(i <= 0) return; final Table data = table(databases.getSelectedItem().toString()); table.update(data); final StringList added = new StringList(); for(final TokenList l : data.contents) added.add(Token.string(l.get(0))); final StringList adding = new StringList(); for(final TokenList l : users.contents) { final String s = Token.string(l.get(0)); if(!s.equals(ADMIN) && !added.contains(s)) adding.add(s); } addUser.addItem(numberof(USERS, adding.size())); for(final String s : adding) addUser.addItem(s); addUser.setSelectedIndex(0); } } /** * Returns a global or local user table. * @param db database (optional) * @return table * @throws IOException I/O exception */ private Table table(final String db) throws IOException { return new Table(sess.execute(new ShowUsers(db))); } /** * Sets session. * @param s session * @throws IOException I/O exception */ public void setSess(final Session s) throws IOException { sess = s; if(!global) { final Table dbs = new Table(sess.execute(new List())); databases.removeAllItems(); databases.addItem(numberof(DATABASES, dbs.contents.size())); for(final TokenList l : dbs.contents) { databases.addItem(Token.string(l.get(0))); } databases.setSelectedIndex(0); } setData(); } /** * Returns the first entry of combo boxes. * @param w what * @param n number * @return String */ private static String numberof(final String w, final int n) { return "(" + n + ' ' + w + ')'; } /** * Returns table panel. * @return BaseXBack */ public BaseXBack getTablePanel() { return tablePanel; } }