From bbc90f4175bb692e125397bbfa46b7709e84bdd2 Mon Sep 17 00:00:00 2001
From: izabel <izabel>
Date: Wed, 24 Sep 2008 06:46:51 +0000
Subject: [PATCH] [LMS-445] Authorization Management Console: roles

SVN: 8444
---
 .../web/client/IGenericClientService.java     |  11 ++
 .../client/IGenericClientServiceAsync.java    |  12 ++
 .../web/client/application/Application.java   |  20 +-
 .../client/application/ui/ColumnFIlter.java   |  50 +++++
 .../web/client/application/ui/GroupsView.java |  20 +-
 .../client/application/ui/PersonModel.java    |   5 +-
 .../client/application/ui/PersonsView.java    |  19 +-
 .../client/application/ui/RoleAssignment.java |  83 ++++++++
 .../web/client/application/ui/RoleBox.java    |  60 ++++++
 .../web/client/application/ui/RoleModel.java  |  33 ++++
 .../client/application/ui/RolesDialog.java    |  91 +++++++++
 .../web/client/application/ui/RolesView.java  | 177 ++++++++++++++++++
 .../web/client/application/ui/TopMenu.java    |   6 +-
 .../client/web/client/dto/RoleCode.java       |  21 +++
 .../client/web/public/generic-dictionary.js   |   2 +-
 .../web/server/GenericClientService.java      |  49 +++++
 .../server/GenericClientServiceServlet.java   |  19 ++
 .../web/server/util/InstanceTranslater.java   |  40 ++++
 .../server/util/RoleAssignmentTranslator.java |  71 +++++++
 .../openbis/generic/server/GenericServer.java |  82 +++++++-
 .../generic/server/GenericServerLogger.java   |  21 +++
 .../server/business/IPersonManager.java       |   8 +
 .../server/business/PersonManager.java        |  35 ++++
 .../server/dataaccess/IRoleAssignmentDAO.java |   4 +
 .../dataaccess/db/RoleAssignmentDAO.java      |  31 +++
 .../generic/shared/IGenericServer.java        |  10 +
 26 files changed, 945 insertions(+), 35 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnFIlter.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleAssignment.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleBox.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleModel.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesDialog.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesView.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/RoleCode.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/InstanceTranslater.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/RoleAssignmentTranslator.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java
index 0c64ccf753e..4cc739fd4e5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientService.java
@@ -20,6 +20,7 @@ import java.util.List;
 
 import com.google.gwt.user.client.rpc.RemoteService;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
@@ -74,4 +75,14 @@ public interface IGenericClientService extends RemoteService
      * Registers a new person with specified code.
      */
     public void registerPerson(String code) throws UserFailureException;
+
+    // FIXME
+    public List<RoleAssignment> listRoles() throws UserFailureException;
+
+    // FIXME
+    public void registerRole(String roleSetCode, String group, String person)
+            throws UserFailureException;
+
+    public void deleteRole(String roleSetCode, String group, String person)
+            throws UserFailureException;
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java
index e8e3b182872..170ffc9f26c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/IGenericClientServiceAsync.java
@@ -20,6 +20,7 @@ import java.util.List;
 
 import com.google.gwt.user.client.rpc.AsyncCallback;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
@@ -57,4 +58,15 @@ public interface IGenericClientServiceAsync
     /** @see IGenericClientService#registerPerson(String) */
     public void registerPerson(String code, AsyncCallback<Void> asyncCallback);
 
+    // FIXME
+    public void listRoles(AsyncCallback<List<RoleAssignment>> asyncCallback);
+
+    // FIXME
+    public void registerRole(String roleSetCode, String group, String person,
+            AsyncCallback<Void> asyncCallback);
+
+    // FIXME
+    public void deleteRole(String roleSetCode, String group, String person,
+            AsyncCallback<Void> asyncCallback);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Application.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Application.java
index 2473bb25a50..8be6fe14ca3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Application.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Application.java
@@ -28,6 +28,7 @@ import com.extjs.gxt.ui.client.widget.layout.RowLayout;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.Footer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupsView;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.PersonsView;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RolesView;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.TopMenu;
 
 /**
@@ -85,24 +86,17 @@ public class Application extends Viewport
             personList.refresh();
             personsTab.add(personList);
 
-            TabItem instanceTab = new TabItem(viewContext.getMessage("instanceView_heading"));
-            instanceTab.addStyleName("pad-text");
-            instanceTab.add(new InstanceView(viewContext));
+            TabItem rolesTab = new TabItem(viewContext.getMessage("rolesView_heading"));
+            rolesTab.addStyleName("pad-text");
+            RolesView roleList = new RolesView(viewContext);
+            roleList.refresh();
+            rolesTab.add(roleList);
 
             add(personsTab);
             add(groupsTab);
-            // add(instance);
-        }
-    }
-
-    class InstanceView extends LayoutContainer
-    {
-
-        public InstanceView(GenericViewContext viewContext)
-        {
+            add(rolesTab);
 
         }
-
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnFIlter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnFIlter.java
new file mode 100644
index 00000000000..7c5e6c2cc86
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ColumnFIlter.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
+
+import com.extjs.gxt.ui.client.data.ModelData;
+import com.extjs.gxt.ui.client.store.Store;
+import com.extjs.gxt.ui.client.widget.StoreFilterField;
+
+/**
+ * @author Izabela Adamczyk
+ */
+class ColumnFilter<T extends ModelData> extends StoreFilterField<T>
+{
+
+    private final String column;
+
+    public ColumnFilter(Store<T> store, String col, String label)
+    {
+        this.column = col;
+        setWidth(100);
+        setEmptyText(label + "...");
+        bind(store);
+    }
+
+    @Override
+    protected boolean doSelect(Store<T> store, T parent, T record, String property, String filter)
+    {
+        String name = record.get(column);
+        name = name.toLowerCase();
+        if (name.startsWith(filter.toLowerCase()))
+        {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupsView.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupsView.java
index 129686d59b4..c061d2b26f5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupsView.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupsView.java
@@ -36,6 +36,10 @@ import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
 import com.extjs.gxt.ui.client.widget.grid.RowExpander;
 import com.extjs.gxt.ui.client.widget.layout.FitLayout;
 import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
+import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.LabelToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
 import com.google.gwt.i18n.client.DateTimeFormat;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
@@ -105,6 +109,8 @@ public class GroupsView extends LayoutContainer
         registrationDateColumnConfig.setDateTimeFormat(DateTimeFormat.getShortDateFormat());
         configs.add(registrationDateColumnConfig);
 
+        final GroupsView groupList = this;
+
         ColumnModel cm = new ColumnModel(configs);
 
         ListStore<GroupModel> store = new ListStore<GroupModel>();
@@ -115,26 +121,30 @@ public class GroupsView extends LayoutContainer
         cp.setHeading("Group list");
         cp.setButtonAlign(HorizontalAlignment.CENTER);
         cp.setIconStyle("icon-table");
-        final GroupsView groupList = this;
 
         cp.setLayout(new FitLayout());
         cp.setSize(600, 300);
 
         Grid<GroupModel> grid = new Grid<GroupModel>(store, cm);
         grid.addPlugin(expander);
-        // grid.setStyleAttribute("borderTop", "none");
-        // grid.setAutoExpandColumn("code");
         grid.setBorders(true);
 
         cp.add(grid);
-        cp.addButton(new Button("Add group", new SelectionListener<ComponentEvent>()
+        Button addGroupBtton = new Button("Add group", new SelectionListener<ComponentEvent>()
             {
                 @Override
                 public void componentSelected(ComponentEvent ce)
                 {
                     new GroupDialog(viewContext, groupList).show();
                 }
-            }));
+            });
+
+        ToolBar toolBar = new ToolBar();
+        toolBar.add(new LabelToolItem("Filter:"));
+        toolBar.add(new AdapterToolItem(new ColumnFilter<GroupModel>(store, "code", "code")));
+        toolBar.add(new SeparatorToolItem());
+        toolBar.add(new AdapterToolItem(addGroupBtton));
+        cp.setBottomComponent(toolBar);
 
         add(cp);
         layout();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonModel.java
index e577bbb9f7e..63132ea79ca 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonModel.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 
+import java.util.ArrayList;
+
 import com.extjs.gxt.ui.client.data.BaseModelData;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
@@ -34,13 +36,12 @@ public class PersonModel extends BaseModelData
 
     public PersonModel(Person p)
     {
-
         set("userId", p.getUserId());
         set("registrator", p.getRegistrator());
         set("registrationDate", p.getRegistrationDate());
         set("firstName", p.getFirstName());
         set("lastName", p.getLastName());
         set("email", p.getEMail());
+        set("roles", new ArrayList<RoleAssignment>());
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonsView.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonsView.java
index 22fbe3eb97e..8c478851647 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonsView.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/PersonsView.java
@@ -34,6 +34,10 @@ import com.extjs.gxt.ui.client.widget.grid.Grid;
 import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
 import com.extjs.gxt.ui.client.widget.layout.FitLayout;
 import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
+import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.LabelToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
 import com.google.gwt.i18n.client.DateTimeFormat;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
@@ -124,18 +128,27 @@ public class PersonsView extends LayoutContainer
         cp.setLayout(new FitLayout());
         cp.setSize(700, 300);
 
-        Grid<PersonModel> grid = new Grid<PersonModel>(store, cm);
+        final Grid<PersonModel> grid = new Grid<PersonModel>(store, cm);
         grid.setBorders(true);
 
         cp.add(grid);
-        cp.addButton(new Button("Add person", new SelectionListener<ComponentEvent>()
+
+        Button addPersonButton = new Button("Add person", new SelectionListener<ComponentEvent>()
             {
                 @Override
                 public void componentSelected(ComponentEvent ce)
                 {
                     new PersonDialog(viewContext, personList).show();
                 }
-            }));
+            });
+
+        ToolBar toolBar = new ToolBar();
+        toolBar.add(new LabelToolItem("Filter:"));
+        toolBar.add(new AdapterToolItem(new ColumnFilter<PersonModel>(store, "userId", "user id")));
+        toolBar.add(new SeparatorToolItem());
+        toolBar.add(new AdapterToolItem(addPersonButton));
+
+        cp.setBottomComponent(toolBar);
 
         add(cp);
         layout();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleAssignment.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleAssignment.java
new file mode 100644
index 00000000000..01641c6af78
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleAssignment.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DatabaseInstance;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
+
+/**
+ * @author Izabela Adamczyk
+ */
+public class RoleAssignment implements IsSerializable
+{
+
+    String code;
+
+    Person person;
+
+    Group group;
+
+    private DatabaseInstance instance;
+
+    public RoleAssignment()
+    {
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public Group getGroup()
+    {
+        return group;
+    }
+
+    public void setGroup(Group group)
+    {
+        this.group = group;
+    }
+
+    public Person getPerson()
+    {
+        return person;
+    }
+
+    public void setPerson(Person person)
+    {
+        this.person = person;
+    }
+
+    public DatabaseInstance getInstance()
+    {
+        return instance;
+    }
+
+    public void setInstance(DatabaseInstance instance)
+    {
+        this.instance = instance;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleBox.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleBox.java
new file mode 100644
index 00000000000..26fbc9cfc5f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleBox.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
+
+import com.extjs.gxt.ui.client.widget.form.TextField;
+import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * @author Izabela Adamczyk
+ */
+public class RoleBox extends ListBox
+{
+
+    public RoleBox(final TextField<String> group)
+    {
+        addItem("OBSERVER");
+        addItem("USER");
+        addItem("GROUP_ADMIN");
+        addItem("INSTANCE_ADMIN");
+        setVisibleItemCount(1);
+
+        addChangeListener(new ChangeListener()
+            {
+                public void onChange(Widget sender)
+                {
+                    if (getSelectedIndex() != 3)
+                    {
+                        group.show();
+                        group.setAllowBlank(false);
+                    } else
+                    {
+                        group.hide();
+                        group.setAllowBlank(true);
+                    }
+                }
+            });
+
+    }
+
+    public String getValue()
+    {
+        return getValue(getSelectedIndex());
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleModel.java
new file mode 100644
index 00000000000..7b35e61f23f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RoleModel.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
+
+import com.extjs.gxt.ui.client.data.BaseModelData;
+
+public class RoleModel extends BaseModelData
+{
+    private static final long serialVersionUID = 1L;
+
+    public RoleModel(RoleAssignment role)
+    {
+        set("group", role.getGroup() != null ? role.getGroup().getCode() : "");
+        set("person", role.getPerson().getUserId());
+        set("role", role.getCode());
+        set("instance", role.getInstance() != null ? role.getInstance().getCode() : "");
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesDialog.java
new file mode 100644
index 00000000000..2de960a313b
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesDialog.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
+
+import com.extjs.gxt.ui.client.event.ComponentEvent;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.widget.Window;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.extjs.gxt.ui.client.widget.form.AdapterField;
+import com.extjs.gxt.ui.client.widget.form.FormPanel;
+import com.extjs.gxt.ui.client.widget.form.TextField;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericViewContext;
+
+/**
+ * @author Izabela Adamczyk
+ */
+public class RolesDialog extends Window
+{
+
+    public RolesDialog(final GenericViewContext viewContext, final RolesView roleList)
+    {
+
+        setHeading("Add a new role");
+        setModal(true);
+        setWidth(400);
+        FormPanel form = new FormPanel();
+        form.setHeaderVisible(false);
+        form.setBorders(false);
+        form.setBodyBorder(false);
+        add(form);
+
+        final TextField<String> group = new TextField<String>();
+        group.setWidth(100);
+        group.setFieldLabel("Group");
+        group.setAllowBlank(false);
+
+        final AdapterField roleBox = new AdapterField(new RoleBox(group));
+        roleBox.setFieldLabel("Role");
+        roleBox.setWidth(100);
+        form.add(roleBox);
+        form.add(group);
+
+        final TextField<String> user = new TextField<String>();
+        user.setWidth(100);
+        user.setFieldLabel("Person");
+        user.setAllowBlank(false);
+        form.add(user);
+
+        addButton(new Button("Save", new SelectionListener<ComponentEvent>()
+            {
+                @Override
+                public void componentSelected(ComponentEvent ce)
+                {
+                    viewContext.getService().registerRole(
+                            ((RoleBox) roleBox.getWidget()).getValue(), group.getValue(),
+                            user.getValue(), new AbstractAsyncCallback<Void>(viewContext)
+                                {
+                                    public void onSuccess(Void result)
+                                    {
+                                        hide();
+                                        roleList.refresh();
+                                    }
+                                });
+                }
+            }));
+        addButton(new Button("Cancel", new SelectionListener<ComponentEvent>()
+            {
+                @Override
+                public void componentSelected(ComponentEvent ce)
+                {
+                    hide();
+                }
+            }));
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesView.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesView.java
new file mode 100644
index 00000000000..2e81c563ab4
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/RolesView.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
+import com.extjs.gxt.ui.client.event.ComponentEvent;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.store.ListStore;
+import com.extjs.gxt.ui.client.widget.ContentPanel;
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.Text;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
+import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
+import com.extjs.gxt.ui.client.widget.grid.Grid;
+import com.extjs.gxt.ui.client.widget.layout.FitLayout;
+import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
+import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.LabelToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericViewContext;
+
+/**
+ * @author Izabela Adamczyk
+ */
+public class RolesView extends LayoutContainer
+{
+
+    private final GenericViewContext viewContext;
+
+    public RolesView(GenericViewContext viewContext)
+    {
+        this.viewContext = viewContext;
+        setLayout(new FlowLayout(5));
+
+    }
+
+    private void display(final List<RoleAssignment> roles)
+    {
+        removeAll();
+
+        List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
+
+        ColumnConfig userIdColumnConfig = new ColumnConfig();
+        userIdColumnConfig.setId("person");
+        userIdColumnConfig.setHeader("Person");
+        userIdColumnConfig.setWidth(80);
+        configs.add(userIdColumnConfig);
+
+        ColumnConfig groupColumnConfig = new ColumnConfig();
+        groupColumnConfig.setId("group");
+        groupColumnConfig.setHeader("Group");
+        groupColumnConfig.setWidth(80);
+        configs.add(groupColumnConfig);
+
+        ColumnConfig instanceColumnConfig = new ColumnConfig();
+        instanceColumnConfig.setId("instance");
+        instanceColumnConfig.setHeader("Database Instance");
+        instanceColumnConfig.setWidth(80);
+        configs.add(instanceColumnConfig);
+
+        ColumnConfig roleColumnConfig = new ColumnConfig();
+        roleColumnConfig.setId("role");
+        roleColumnConfig.setHeader("Role");
+        roleColumnConfig.setWidth(120);
+        configs.add(roleColumnConfig);
+
+        ColumnModel cm = new ColumnModel(configs);
+
+        final ListStore<RoleModel> store = new ListStore<RoleModel>();
+        store.add(getRoleModels(roles));
+
+        ContentPanel cp = new ContentPanel();
+        cp.setBodyBorder(false);
+        cp.setHeading("Role list");
+        cp.setButtonAlign(HorizontalAlignment.CENTER);
+        cp.setIconStyle("icon-table");
+        final RolesView roleList = this;
+
+        cp.setLayout(new FitLayout());
+        cp.setSize(700, 300);
+
+        final Grid<RoleModel> grid = new Grid<RoleModel>(store, cm);
+        grid.setBorders(true);
+
+        cp.add(grid);
+
+        Button addRoleButton = new Button("Add role", new SelectionListener<ComponentEvent>()
+            {
+                @Override
+                public void componentSelected(ComponentEvent ce)
+                {
+                    new RolesDialog(viewContext, roleList).show();
+                }
+            });
+
+        Button removeRoleButton = new Button("Remove role", new SelectionListener<ComponentEvent>()
+            {
+                @Override
+                public void componentSelected(ComponentEvent ce)
+                {
+                    final RoleModel rm = grid.getSelectionModel().getSelectedItem();
+                    viewContext.getService().deleteRole((String) rm.get("role"),
+                            (String) rm.get("group"), (String) rm.get("person"),
+                            new AbstractAsyncCallback<Void>(viewContext)
+                                {
+                                    public void onSuccess(Void result)
+                                    {
+                                        roleList.refresh();
+                                    }
+                                });
+                }
+            });
+
+        ToolBar toolBar = new ToolBar();
+        toolBar.add(new LabelToolItem("Filter:"));
+        toolBar.add(new AdapterToolItem(new ColumnFilter<RoleModel>(store, "person", "person")));
+        toolBar.add(new AdapterToolItem(new ColumnFilter<RoleModel>(store, "group", "group")));
+        toolBar
+                .add(new AdapterToolItem(new ColumnFilter<RoleModel>(store, "instance", "instance")));
+        toolBar.add(new AdapterToolItem(new ColumnFilter<RoleModel>(store, "role", "role")));
+        toolBar.add(new SeparatorToolItem());
+        toolBar.add(new AdapterToolItem(addRoleButton));
+        toolBar.add(new SeparatorToolItem());
+        toolBar.add(new AdapterToolItem(removeRoleButton));
+        cp.setBottomComponent(toolBar);
+        add(cp);
+        layout();
+
+    }
+
+    List<RoleModel> getRoleModels(List<RoleAssignment> roles)
+    {
+        List<RoleModel> roleModel = new ArrayList<RoleModel>();
+        for (RoleAssignment role : roles)
+        {
+            roleModel.add(new RoleModel(role));
+        }
+        return roleModel;
+    }
+
+    public void refresh()
+    {
+        removeAll();
+        add(new Text("data loading..."));
+        viewContext.getService().listRoles(
+                new AbstractAsyncCallback<List<RoleAssignment>>(viewContext)
+                    {
+                        public void onSuccess(List<RoleAssignment> roles)
+                        {
+                            display(roles);
+                        }
+
+                    });
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TopMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TopMenu.java
index f3e90c50466..23bd78b4b5d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TopMenu.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TopMenu.java
@@ -19,9 +19,8 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 import com.extjs.gxt.ui.client.event.ComponentEvent;
 import com.extjs.gxt.ui.client.event.SelectionListener;
 import com.extjs.gxt.ui.client.widget.LayoutContainer;
-import com.extjs.gxt.ui.client.widget.Text;
 import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
-import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
+import com.extjs.gxt.ui.client.widget.toolbar.LabelToolItem;
 import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
 import com.extjs.gxt.ui.client.widget.toolbar.TextToolItem;
 import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
@@ -41,7 +40,8 @@ public class TopMenu extends LayoutContainer
         setLayout(new FlowLayout());
         setBorders(true);
         ToolBar toolBar = new ToolBar();
-        toolBar.add(new AdapterToolItem(new Text(createUserInfo(viewContext))));
+        LabelToolItem userInfoText = new LabelToolItem(createUserInfo(viewContext));
+        toolBar.add(userInfoText);
         toolBar.add(new SeparatorToolItem());
         toolBar.add(new LogoutButton(viewContext));
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/RoleCode.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/RoleCode.java
new file mode 100644
index 00000000000..f34181cfdff
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/RoleCode.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.dto;
+public enum RoleCode
+{
+    ADMIN, USER, OBSERVER, ETL_SERVER;
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/public/generic-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/public/generic-dictionary.js
index 8da9458ecec..b32890ef39b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/public/generic-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/public/generic-dictionary.js
@@ -27,7 +27,7 @@ var generic = {
   
   personsView_heading: "Persons",
   groupsView_heading: "Groups",
-  instanceView_heading: "Instance",
+  rolesView_heading: "Roles",
   
   lastline: "" // we need a line without a comma
 };
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java
index 0415f8fa04b..51dc5766fde 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientService.java
@@ -30,6 +30,7 @@ import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.servlet.IRequestContextProvider;
 import ch.systemsx.cisd.common.utilities.BuildAndEnvironmentInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.IGenericClientService;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
@@ -37,10 +38,12 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.User;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.GroupTranslater;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.PersonTranslator;
+import ch.systemsx.cisd.openbis.generic.client.web.server.util.RoleAssignmentTranslator;
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.UserFailureExceptionTranslater;
 import ch.systemsx.cisd.openbis.generic.shared.IGenericServer;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 
@@ -243,4 +246,50 @@ public class GenericClientService implements IGenericClientService
         }
     }
 
+    public List<RoleAssignment> listRoles()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            List<RoleAssignment> result = new ArrayList<RoleAssignment>();
+            List<RoleAssignmentPE> roles = server.listRoles(getSessionToken());
+            for (RoleAssignmentPE role : roles)
+            {
+                result.add(RoleAssignmentTranslator.translate(role));
+            }
+            return result;
+        } catch (UserFailureException e)
+        {
+            throw UserFailureExceptionTranslater.translate(e);
+        }
+    }
+
+    public void registerRole(String roleSetCode, String group, String person)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            String sessionToken = getSessionToken();
+            server.registerRole(sessionToken, roleSetCode, group, person);
+        } catch (UserFailureException e)
+        {
+            throw UserFailureExceptionTranslater.translate(e);
+        }
+
+    }
+
+    public void deleteRole(String roleSetCode, String group, String person)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            String sessionToken = getSessionToken();
+            server.deleteRole(sessionToken, roleSetCode, group, person);
+        } catch (UserFailureException e)
+        {
+            throw UserFailureExceptionTranslater.translate(e);
+        }
+
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java
index d65e871037c..2a370671944 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/GenericClientServiceServlet.java
@@ -33,6 +33,7 @@ import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.servlet.GWTSpringController;
 import ch.systemsx.cisd.common.spring.ExposablePropertyPaceholderConfigurer;
 import ch.systemsx.cisd.openbis.generic.client.web.client.IGenericClientService;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Person;
@@ -138,4 +139,22 @@ public class GenericClientServiceServlet extends GWTSpringController implements
 
     }
 
+    public List<RoleAssignment> listRoles() throws UserFailureException
+    {
+        return service.listRoles();
+    }
+
+    public void registerRole(String roleSetCode, String group, String person)
+            throws UserFailureException
+    {
+        service.registerRole(roleSetCode, group, person);
+    }
+
+    public void deleteRole(String roleSetCode, String group, String person)
+            throws UserFailureException
+    {
+        service.deleteRole(roleSetCode, group, person);
+
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/InstanceTranslater.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/InstanceTranslater.java
new file mode 100644
index 00000000000..6541d7fef52
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/InstanceTranslater.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.server.util;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DatabaseInstance;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+
+/**
+ * @author Izabela Adamczyk
+ */
+public class InstanceTranslater
+{
+
+    public static DatabaseInstance translate(DatabaseInstancePE databaseInstance)
+    {
+        if (databaseInstance == null)
+        {
+            return null;
+        }
+        DatabaseInstance result = new DatabaseInstance();
+        result.setCode(databaseInstance.getCode());
+        result.setUuid(databaseInstance.getUuid());
+        return result;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/RoleAssignmentTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/RoleAssignmentTranslator.java
new file mode 100644
index 00000000000..a39893ecb3e
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/util/RoleAssignmentTranslator.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.server.util;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.RoleAssignment;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
+
+public class RoleAssignmentTranslator
+{
+    private RoleAssignmentTranslator()
+    {
+    }
+
+    public static RoleAssignment translate(RoleAssignmentPE role)
+    {
+        if (role == null)
+        {
+            return null;
+        }
+        RoleAssignment result = new RoleAssignment();
+        result.setGroup(GroupTranslater.translate(role.getGroup()));
+        result.setInstance(InstanceTranslater.translate(role.getDatabaseInstance()));
+        result.setPerson(PersonTranslator.translate(role.getPerson()));
+        result.setCode(getRoleCode(role));
+        return result;
+    }
+
+    private static String getRoleCode(RoleAssignmentPE role)
+    {
+        String code;
+        switch (role.getRole())
+        {
+            case ADMIN:
+                if (role.getGroup() == null)
+                {
+                    code = "INSTANCE_ADMIN";
+                } else
+                {
+                    code = "GROUP_ADMIN";
+                }
+                break;
+            case OBSERVER:
+                code = "OBSERVER";
+                break;
+            case USER:
+                code = "USER";
+                break;
+            case ETL_SERVER:
+                code = "ETL_SERVER";
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown role");
+        }
+        return code;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java
index 8a37250e22e..fd439633452 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServer.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.server;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
 import org.hibernate.Hibernate;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -35,6 +36,7 @@ import ch.systemsx.cisd.common.spring.IInvocationLoggerFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.GenericBusinessObjectFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGenericBusinessObjectFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.util.GroupIdentifierHelper;
 import ch.systemsx.cisd.openbis.generic.shared.IGenericServer;
@@ -42,11 +44,13 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.ISessionProvider;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IAuthSession;
+import ch.systemsx.cisd.openbis.generic.shared.dto.NewRoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
 
 /**
  * Implementation of client-server interface.
@@ -185,14 +189,6 @@ public class GenericServer implements IGenericServer, ISessionProvider,
         groupBO.save();
     }
 
-    @Transactional
-    public List<PersonPE> listPersons(String sessionToken)
-    {
-        sessionManager.getSession(sessionToken);
-        List<PersonPE> persons = daoFactory.getPersonDAO().listPersons();
-        return persons;
-    }
-
     @Transactional
     public void registerPerson(String sessionToken, String userID)
     {
@@ -218,4 +214,74 @@ public class GenericServer implements IGenericServer, ISessionProvider,
         }
     }
 
+    public List<RoleAssignmentPE> listRoles(String sessionToken)
+    {
+        sessionManager.getSession(sessionToken);
+        return daoFactory.getRoleAssignmentDAO().listRoleAssignments();
+    }
+
+    public void registerRole(String sessionToken, String roleSetCode, String group, String person)
+    {
+        Session session = sessionManager.getSession(sessionToken);
+
+        NewRoleAssignment newRoleAssignment = new NewRoleAssignment();
+        newRoleAssignment.setUserId(person);
+        if (StringUtils.isBlank(group) == false)
+        {
+            newRoleAssignment.setGroupIdentifier(new GroupIdentifier(
+                    DatabaseInstanceIdentifier.HOME, group));
+        }
+        newRoleAssignment.setRole(translateRoleSetCode(roleSetCode));
+
+        final IRoleAssignmentTable table = boFactory.createRoleAssignmentTable(session);
+        table.add(newRoleAssignment);
+        table.save();
+
+    }
+
+    private RoleCode translateRoleSetCode(String code)
+    {
+
+        if ("INSTANCE_ADMIN".compareTo(code) == 0)
+        {
+            return RoleCode.ADMIN;
+        } else if ("GROUP_ADMIN".compareTo(code) == 0)
+        {
+            return RoleCode.ADMIN;
+        } else if ("USER".compareTo(code) == 0)
+        {
+            return RoleCode.USER;
+        } else if ("OBSERVER".compareTo(code) == 0)
+        {
+            return RoleCode.OBSERVER;
+        } else
+        {
+            throw new IllegalArgumentException("Unknown role set");
+        }
+
+    }
+
+    public void deleteRole(String sessionToken, String roleSetCode, String group, String person)
+    {
+
+        sessionManager.getSession(sessionToken);
+
+        RoleAssignmentPE roleAssignment =
+                daoFactory.getRoleAssignmentDAO().getRoleAssignment(
+                        translateRoleSetCode(roleSetCode), group, person);
+        if (roleAssignment == null)
+        {
+            throw new UserFailureException("Given role does not exist.");
+        }
+        daoFactory.getRoleAssignmentDAO().deleteRoleAssignment(roleAssignment);
+    }
+
+    @Transactional
+    public List<PersonPE> listPersons(String sessionToken)
+    {
+        sessionManager.getSession(sessionToken);
+        List<PersonPE> persons = daoFactory.getPersonDAO().listPersons();
+        return persons;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServerLogger.java
index 8874c178bd1..a916aee7dfb 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/GenericServerLogger.java
@@ -28,6 +28,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.ISessionProvider;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IAuthSession;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 
@@ -168,4 +169,24 @@ class GenericServerLogger implements IGenericServer, ISessionProvider
 
     }
 
+    public List<RoleAssignmentPE> listRoles(String sessionToken)
+    {
+        logAccess(sessionToken, "list_roles", "");
+        return null;
+    }
+
+    public void registerRole(String sessionToken, String roleSetCode, String group, String person)
+    {
+        logTracking(sessionToken, "register_role", "ROLE(%s) GROUP(%s) PERSON(%s)", roleSetCode,
+                group, person);
+
+    }
+
+    public void deleteRole(String sessionToken, String roleSetCode, String group, String person)
+    {
+        logTracking(sessionToken, "delete_role", "ROLE(%s) GROUP(%s) PERSON(%s)", roleSetCode,
+                group, person);
+
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/IPersonManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/IPersonManager.java
index 090e043ef90..6e2ebacf837 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/IPersonManager.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/IPersonManager.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.server.business;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
 import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewRoleAssignment;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
 
@@ -41,4 +42,11 @@ public interface IPersonManager
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
     public void registerRoleAssignments(Session session, NewRoleAssignment[] roleAssignments);
 
+
+    // FXME
+    public void deleteRoleAssignments(Session session, RoleCode translateRoleSetCode, String group,
+            String person);
+
+    // FIXME
+    public void registerRoleAssignment(Session session, NewRoleAssignment newRoleAssignment);
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/PersonManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/PersonManager.java
index bea1b5b7083..8b3a21ddd33 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/PersonManager.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/PersonManager.java
@@ -21,12 +21,15 @@ import static ch.systemsx.cisd.common.utilities.ParameterChecker.checkIfNotNull;
 
 import org.springframework.transaction.annotation.Transactional;
 
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGenericBusinessObjectFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IPersonBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAuthorizationDAOFactory;
 import ch.systemsx.cisd.openbis.generic.shared.dto.NewRoleAssignment;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.GroupIdentifier;
 
@@ -78,4 +81,36 @@ final class PersonManager extends AbstractManager implements IPersonManager
         table.save();
     }
 
+    @Transactional
+    public final void registerRoleAssignment(final Session session,
+            final NewRoleAssignment roleAssignment)
+    {
+        assert session != null : "Unspecified session";
+        checkIfNotNull(roleAssignment, "role assignment");
+
+        final IRoleAssignmentTable table = boFactory.createRoleAssignmentTable(session);
+        table.add(roleAssignment);
+        table.save();
+    }
+
+    @Transactional
+    public void registerPerson(Session session, String code)
+    {
+        assert session != null : "Unspecified session";
+        IPersonBO personBO = boFactory.createPersonBO(session);
+        personBO.registerPerson(code);
+    }
+
+    @Transactional
+    public void deleteRoleAssignments(Session session, RoleCode role, String group, String person)
+    {
+        RoleAssignmentPE roleAssignment =
+                daoFactory.getRoleAssignmentDAO().getRoleAssignment(role, group, person);
+        if (roleAssignment == null)
+        {
+            throw new UserFailureException("Given role does not exist.");
+        }
+        daoFactory.getRoleAssignmentDAO().deleteRoleAssignment(roleAssignment);
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IRoleAssignmentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IRoleAssignmentDAO.java
index 42ff809b3c9..8bc0a6a34a6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IRoleAssignmentDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IRoleAssignmentDAO.java
@@ -22,6 +22,7 @@ import org.springframework.dao.DataAccessException;
 
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 
 /**
  * <i>Data Access Object</i> for {@link RoleAssignmentPE}.
@@ -53,4 +54,7 @@ public interface IRoleAssignmentDAO
      * Lists all role assignments found in the database for given <var>personId</var>.
      */
     public List<RoleAssignmentPE> listRoleAssignmentsByPerson(final PersonPE person);
+
+    // FIXME
+    public RoleAssignmentPE getRoleAssignment(RoleCode role, String group, String person);
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/RoleAssignmentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/RoleAssignmentDAO.java
index 3f64fc07a56..86ece697dc7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/RoleAssignmentDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/RoleAssignmentDAO.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
 
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.hibernate.SessionFactory;
 import org.hibernate.criterion.Criterion;
@@ -32,6 +33,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IRoleAssignmentDAO;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleCode;
 
 /**
  * <i>Data Access Object</i> implementation for {@link RoleAssignmentPE}.
@@ -106,4 +108,33 @@ public final class RoleAssignmentDAO extends AbstractDAO implements IRoleAssignm
         }
     }
 
+    public RoleAssignmentPE getRoleAssignment(RoleCode role, String group, String person)
+    {
+        List<RoleAssignmentPE> roles;
+        if (StringUtils.isBlank(group) == false)
+        {
+            roles =
+                    cast(getHibernateTemplate().find(
+                            String.format("from %s r where r.person.userId = ? and group.code = ? "
+                                    + "and r.role = ?", ENTITY_CLASS.getSimpleName()), new Object[]
+                                { person, group, role }));
+        } else
+        {
+            roles =
+                    cast(getHibernateTemplate().find(
+                            String.format(
+                                    "from %s r where r.person.userId = ? and group.code IS NULL "
+                                            + "and r.role = ? and r.databaseInstance = ?",
+                                    ENTITY_CLASS.getSimpleName()), new Object[]
+                                { person, role, getDatabaseInstance() }));
+        }
+        final RoleAssignmentPE roleAssignment =
+                tryFindEntity(roles, "role_assignments", role, group, person);
+        if (operationLog.isInfoEnabled())
+        {
+            operationLog.info(String.format("FIND: role assignment '%s'.", roleAssignment));
+        }
+        return roleAssignment;
+
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java
index 967f3ef9039..e16463a6d57 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IGenericServer.java
@@ -24,6 +24,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAll
 import ch.systemsx.cisd.openbis.generic.shared.authorization.validator.GroupValidator;
 import ch.systemsx.cisd.openbis.generic.shared.dto.GroupPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 
@@ -77,4 +78,13 @@ public interface IGenericServer
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
     public void registerPerson(String sessionToken, String userID);
 
+    // FIXME
+    public List<RoleAssignmentPE> listRoles(String sessionToken);
+
+    // FIXME
+    public void registerRole(String sessionToken, String roleSetCode, String group, String person);
+
+    // FIXME
+    public void deleteRole(String sessionToken, String roleSetCode, String group, String person);
+
 }
-- 
GitLab