Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Scout/Tutorial/3.8/Minicrm/Permissions"

< Scout‎ | Tutorial‎ | 3.8‎ | Minicrm
(Person Form: Make sure you use the same class names if you want to copy and paste the SQL statements later in this section.)
(Administration View: finish permissions)
Line 209: Line 209:
  
 
Additional table pages might be useful: which roles use a particular permission? which users have a particular role? These are left as an exercise for the reader.
 
Additional table pages might be useful: which roles use a particular permission? which users have a particular role? These are left as an exercise for the reader.
 +
 +
=== Permission Table Page and Outline Service ===
 +
 +
We'll be using this table in two places, thus we need a variable for the role ('''RoleNr''').
 +
 +
If a role is provided, we need a service on the server side to provide these. Create a new outline service ('''AdministrationOutlineService''') with an operation to get all the roles ('''getRoleTableData''') with a single argument of type Long ('''roleNr''').
 +
 +
<source lang="java">
 +
@Override
 +
public Object[][] getRoleTableData(Long roleNr) throws ProcessingException {
 +
  return SQL.select("" +
 +
      "SELECT PERMISSION_NAME " +
 +
      "FROM ROLE_PERSMISSION " +
 +
      "WHERE ROLE_NR = :roleNr "
 +
      , new NVPair("roleNr", roleNr));
 +
}
 +
</source>
 +
 +
If no role is provided, we list all the permissions. These are all available on the client. We don't need service on the server side to fetch them. Thus, on the client side, things look a bit different:
 +
 +
<source lang="java">
 +
@Override
 +
protected Object[][] execLoadTableData(SearchFilter filter) throws ProcessingException {
 +
  if (getRoleNr() == null) {
 +
    ArrayList<String> rows = new ArrayList<String>();
 +
    BundleClassDescriptor[] permissions = SERVICES.getService(IPermissionService.class).getAllPermissionClasses();
 +
    for (int i = 0; i < permissions.length; i++) {
 +
      if (permissions[i].getBundleSymbolicName().contains("minicrm")) {
 +
rows.add(permissions[i].getSimpleClassName());
 +
      }
 +
      else {
 +
// Skip bookmark permissions and other permissions that are not specific to our application
 +
      }
 +
    }
 +
    Collections.sort(rows);
 +
    Object[][] data = new Object[rows.size()][1];
 +
    for (int i = 0; i < rows.size(); i++) {
 +
      data[i][0] = rows.get(i);
 +
    }
 +
    return data;
 +
  }
 +
  else {
 +
    return SERVICES.getService(IAdministrationOutlineService.class).getRoleTableData(getRoleNr());
 +
  }
 +
}
 +
</source>
 +
 +
Don't forget to create a column for your table page!
 +
 +
This is what you'd like to see:
 +
 +
[[Image:Minicrm Administration Permissions.png]]
 +
 +
(Using the Swing client.)

Revision as of 06:11, 24 October 2012

The Scout documentation has been moved to https://eclipsescout.github.io/.

Note.png
Scout Tutorial
This page belongs to the Minicrm Step-by-Step Tutorial. It explains how to work with permissions. You need to have a solid understanding of the previous chapters.


What is this chapter about?

This chapter is about authorization and authentication.

When creating forms and table pages, the wizards have always created Permission classes in the background:

  • CreateCompanyPermission
  • ReadCompanyPermission
  • UpdateCompanyPermission
  • DeleteCompanyPermission (actually, you will have to create this permission yourself if you implement a delete menu)

We want to create an Administration View where Users get assigned Roles. These Roles have have Permissions. When a user logs in, the appropriate Permissions are loaded.

For this to work, users must be authenticated. We'll add a SecurityFilter to handle this.

This chapter assumes that you're pretty proficient at creating tables, forms and services. No more hand-holding. :)

Database

The sample database already contains the following tables:

ROLE       ROLE_PERMISSION  USER_ROLE
---------  ---------------  ---------
ROLE_NR    ROLE_NR          USER_NR
NAME       PERMISSION_NAME  ROLE_NR

The PERSON table has a USERNAME column.

Let us create two roles before we get started:

INSERT INTO minicrm.ROLE (role_nr, name) VALUES (1, 'Administrator');
INSERT INTO minicrm.ROLE (role_nr, name) VALUES (2, 'Standard');

Roles

Create a new Lookup Call RoleLookupCall.

The RoleLookupService uses this statement:

    return "" +
        "SELECT  ROLE_NR, " +
        "        NAME " +
        "FROM    ROLE " +
        "WHERE   1=1 " +
        "<key>   AND ROLE_NR = :key </key> " +
        "<text>  AND UPPER(NAME) LIKE UPPER(:text||'%') </text> " +
        "<all> </all> ";

Person Form

Create a Person Form and a Person Process Service to create and edit persons. Make sure you use the same class names if you want to copy and paste the SQL statements later in this section.

Label Class Name Column Name Type
Name NameField LAST_NAME String
First Name FirstNameField FIRST_NAME
Employer EmployerField COMPANY_NR SmartField (CompanyLookupCall)
Username UsernameField USERNAME String
Roles RolesField USER_ROLE.ROLE_NR Listview (RoleLookupCall, Grid H 4)

Menus

Add a "New Person..." and a "Edit Person..." menu to the PersonTablePage.

@Override
protected void execAction() throws ProcessingException {
  PersonForm form = new PersonForm();
  form.startNew();
  form.waitFor();
  if (form.isFormStored()) {
    reloadPage();
  }
}
@Override
public void execAction() throws ProcessingException {
  PersonForm form = new PersonForm();
  form.setPersonNr(getPersonNrColumn().getSelectedValue());
  form.startModify();
  form.waitFor();
 
  if (form.isFormStored()) {
    reloadPage();
  }
}

Process Service

Here are the SQL statements you will need.

Creation:

SQL.selectInto("" +
    "SELECT MAX(PERSON_NR)+1 " +
    "FROM   PERSON " +
    "INTO   :personNr"
    , formData);
 
SQL.insert("" +
    "INSERT INTO PERSON (PERSON_NR, LAST_NAME, FIRST_NAME, COMPANY_NR, USERNAME) " +
    "VALUES (:personNr, :name, :firstName, :employer, :username)"
    , formData);
 
SQL.insert("" +
    "INSERT INTO USER_ROLE (USER_NR, ROLE_NR) " +
    "VALUES (:personNr, :{roles})"
    , formData);

Loading:

SQL.selectInto("" +
    "SELECT LAST_NAME, " +
    "       FIRST_NAME, " +
    "       COMPANY_NR, " +
    "       USERNAME " +
    "FROM   PERSON " +
    "WHERE  PERSON_NR = :personNr " +
    "INTO   :name, " +
    "       :firstName, " +
    "       :employer, " +
    "       :username"
    , formData);
 
SQL.select("" +
    "SELECT ROLE_NR " +
    "FROM USER_ROLE " +
    "WHERE USER_NR = :personNr " +
    "INTO :roles"
    , formData);

Updating:

SQL.update("" +
    "UPDATE PERSON SET" +
    "       LAST_NAME = :name, " +
    "       FIRST_NAME = :firstName, " +
    "       COMPANY_NR = :employer, " +
    "       USERNAME = :username " +
    "WHERE  PERSON_NR = :personNr"
    , formData);
 
SQL.delete("" +
    "DELETE FROM USER_ROLE " +
    "WHERE  USER_NR = :personNr "
    , formData);
 
SQL.insert("" +
    "INSERT INTO USER_ROLE (USER_NR, ROLE_NR) " +
    "VALUES (:personNr, :{roles})"
    , formData);

Screenshot

If you're working in a multilingual environment, this is what it might look like:

Personen.png

Administration View

Create the following outline on the client side:

Administration Outline
 │
 ├─Role Table Page
 │  │
 │  └─Permission Table Page
 │
 └─Permission Table Page

Additional table pages might be useful: which roles use a particular permission? which users have a particular role? These are left as an exercise for the reader.

Permission Table Page and Outline Service

We'll be using this table in two places, thus we need a variable for the role (RoleNr).

If a role is provided, we need a service on the server side to provide these. Create a new outline service (AdministrationOutlineService) with an operation to get all the roles (getRoleTableData) with a single argument of type Long (roleNr).

@Override
public Object[][] getRoleTableData(Long roleNr) throws ProcessingException {
  return SQL.select("" +
      "SELECT PERMISSION_NAME " +
      "FROM ROLE_PERSMISSION " +
      "WHERE ROLE_NR = :roleNr "
      , new NVPair("roleNr", roleNr));
}

If no role is provided, we list all the permissions. These are all available on the client. We don't need service on the server side to fetch them. Thus, on the client side, things look a bit different:

@Override
protected Object[][] execLoadTableData(SearchFilter filter) throws ProcessingException {
  if (getRoleNr() == null) {
    ArrayList<String> rows = new ArrayList<String>();
    BundleClassDescriptor[] permissions = SERVICES.getService(IPermissionService.class).getAllPermissionClasses();
    for (int i = 0; i < permissions.length; i++) {
      if (permissions[i].getBundleSymbolicName().contains("minicrm")) {
	rows.add(permissions[i].getSimpleClassName());
      }
      else {
	// Skip bookmark permissions and other permissions that are not specific to our application
      }
    }
    Collections.sort(rows);
    Object[][] data = new Object[rows.size()][1];
    for (int i = 0; i < rows.size(); i++) {
      data[i][0] = rows.get(i);
    }
    return data;
  }
  else {
    return SERVICES.getService(IAdministrationOutlineService.class).getRoleTableData(getRoleNr());
  }
}

Don't forget to create a column for your table page!

This is what you'd like to see:

Minicrm Administration Permissions.png

(Using the Swing client.)

Back to the top