Friday, April 24, 2020

ユーザ、グループと組織の関係に役立つ便利なツール(その2)

前回、ユーザからユーザの所属または所有ロールを取得するための便利なUserBagを紹介しました。今回は、その逆方向、組織の下の全てユーザ、あるロールにアサインした全てのユーザ、またはサイトメンバー全員を取る方法を紹介しようと思います。

実は、Liferayのポータル機能として、ユーザ管理、ロール管理またはサイトメンバー一覧などの画面で、すでに上記機能が実装されていますが、その画面が利用したメソッドは、ポートレットからの呼び出しを前提としたシグネチャーを持っています(すなわち、PortletRequestHttpServletRequestなど)。 Liferayカスタマイズの際、サービスレイヤからそういう機能を実装する場面が多いため、今回の内容は、Liferayの既存機能の中のxxxRequestなどポートレット特化のパラメーターを利用しないこととします(すなわち本来xxxRequestから作成したものをハードコードで作成する)。

UserSearch

LiferayのUsersAdminPortletまたはSiteMembershipsPortletのユーザリスト部分を確認するとユーザ管理のViewUsersManagementToolbarDisplayContext.javaまたはサイトメンバー管理のUsersDisplayContext.java、よくUserSearchというクラスを見ます。さらに、Liferayには、階層構造を用いてデータベースの検索よりサーチエンジンの検索が早いことを利用し、指定条件のユーザを取得できるメソッドが用意されています。

// UsersDisplayContext.java
UserSearch userSearch = new UserSearch(_renderRequest, getPortletURL());
UserSearchTerms searchTerms =
 (UserSearchTerms)userSearch.getSearchTerms();

LinkedHashMap userParams = new LinkedHashMap<>();
userParams.put("inherit", Boolean.TRUE);
userParams.put("usersGroups", Long.valueOf(getGroupId()));

int usersCount = UserLocalServiceUtil.searchCount(
 themeDisplay.getCompanyId(), searchTerms.getKeywords(),
 searchTerms.getStatus(), userParams);

userSearch.setTotal(usersCount);

List users = UserLocalServiceUtil.search(
 themeDisplay.getCompanyId(), searchTerms.getKeywords(),
 searchTerms.getStatus(), userParams, userSearch.getStart(),
 userSearch.getEnd(), userSearch.getOrderByComparator());

userSearch.setResults(users);
そして、UserSearch.javaUserSearchTerms.javaなどのソースを参照し、以下のようなサービスレイヤ向けUserSearchが作成できます。
  • searchTerms.getKeywords()のデフォルト値はnullになる
  • ユーザ全体を取りたい場合、start=0end=総数を指定する
  • userSearch.getOrderByComparator()のデフォルト値はUsersAdminUtil.getUserOrderByComparator("last-name", "asc")になる
Component(
 property = {
  "osgi.command.scope=liferay",
  "osgi.command.function=checkOrganizationUsers",
  "osgi.command.function=checkSiteUsers",
  "osgi.command.function=checkRoleUsers"
 },
 service = SiteUserOrgCmd.class
)
public class SiteUserOrgCmd {

 private static final long companyId = PortalUtil.getDefaultCompanyId();

 public void checkOrganizationUsers(String orgName) throws Exception {

  Organization org = OrganizationLocalServiceUtil.getOrganization(companyId, orgName);

  LinkedHashMap userParams = new LinkedHashMap();
  userParams.put("inherit", Boolean.TRUE);
  userParams.put("usersOrgs", org.getOrganizationId());
  int usersCount = UserLocalServiceUtil.searchCount(companyId, StringPool.BLANK, WorkflowConstants.STATUS_APPROVED, userParams);
  OrderByComparator obc = UsersAdminUtil.getUserOrderByComparator("last-name", "asc");
  List res = UserLocalServiceUtil.search(companyId, StringPool.BLANK, WorkflowConstants.STATUS_APPROVED, userParams, 0, usersCount, obc);

  System.out.println("Users of organization " + orgName + ": ");
  for (User u : res) {
   System.out.println("  " + u.getScreenName());
  }

 }

 public void checkSiteUsers(String siteName) throws Exception {

  Group grp = null;
  for (Group g : GroupLocalServiceUtil.getGroups(QueryUtil.ALL_POS, QueryUtil.ALL_POS)) {
   if (g.getName(Locale.getDefault()).equals(siteName)) {
    grp = g;
    break;
   }
  }

  LinkedHashMap userParams = new LinkedHashMap();
  userParams.put("inherit", Boolean.TRUE);
  userParams.put("usersGroups", grp.getGroupId());
  int usersCount = UserLocalServiceUtil.searchCount(companyId, StringPool.BLANK, WorkflowConstants.STATUS_APPROVED, userParams);
  OrderByComparator obc = UsersAdminUtil.getUserOrderByComparator("last-name", "asc");
  List res = UserLocalServiceUtil.search(companyId, StringPool.BLANK, WorkflowConstants.STATUS_APPROVED, userParams, 0, usersCount, obc);

  System.out.println("Users of site " + siteName + ": ");
  for (User u : res) {
   System.out.println("  " + u.getScreenName());
  }

 }

 public void checkRoleUsers(String roleName) throws Exception {

  Role role = RoleLocalServiceUtil.getRole(companyId, roleName);

  LinkedHashMap userParams = new LinkedHashMap();
  userParams.put("inherit", Boolean.TRUE);
  userParams.put("usersRoles", role.getRoleId());
  int usersCount = UserLocalServiceUtil.searchCount(companyId, StringPool.BLANK, WorkflowConstants.STATUS_APPROVED, userParams);
  OrderByComparator obc = UsersAdminUtil.getUserOrderByComparator("last-name", "asc");
  List res = UserLocalServiceUtil.search(companyId, StringPool.BLANK, WorkflowConstants.STATUS_APPROVED, userParams, 0, usersCount, obc);

  System.out.println("Users of site " + roleName + ": ");
  for (User u : res) {
   System.out.println("  " + u.getScreenName());
  }
 }
}

検証


前回と同じ、検証用エンティティを作成しましょう。

  • ユーザ: ub_user, ub_user2, ub_user3
  • ユーザグループ: ub_grp
  • 組織: ub_org
    • ub_orgの下の階層にob_org1を作成する
  • サイト: ub_site
  • 一般ロール: ub_role

では、上記サービスでUserSearchの効果を検証しましょう。

組織

  •  ub_org <- ub_user2ub_org1 <- ub_user3
g! checkSiteUsers ub_site
Users of site ub_site:
  test
  ub_user
  ub_user3
  ub_user2

  • 前回同様、dxp-14パッチまでのLiferayには、ub_user3を直接にub_orgにアサインしなくで、その下のub_org1にアサインすると、ub_user3ub_siteのサイトメンバーとして認識できなくなります。

ロール

ub_roleを:
  • ub_userにアサインする
  • ub_grpにアサインし、ub_user2ub_grpにアサインする
  • ub_orgにアサインし、ub_user3ub_orgにアサインする
g! checkRoleUsers ub_role
Users of site ub_role:
  ub_user
  ub_user3
  ub_user2

まとめ

今回、Liferayが提供するUserSearchを利用し、サイト、組織またはロールの所属ユーザを全部取得する方法を紹介しました。実は、UserSearchだけではなく、RoleSearchUserGroupSearchGroupSearchなどのsearch系メソッドがLiferay中に定義されています。このようなクラスを同じ手段で改造したら、サービスレイヤであるエンティティーの下のロール、ユーザグループの取得も可能になります。

No comments: