Forum Discussion

diptikaushikkar's avatar
5 years ago

how to customize custom component based on role ?

What is the best way to customize a custom component to be visible to only some users with some specific roles ??

  • diptikaushikkar 

    You can use below code in your custom component with this function to re-use in areas.

    <#function user_has_role (id, roles)>
      <#assign liql = "SELECT id FROM users WHERE roles.name IN (${roles}) and id = '${id}'" />
      <#assign query = rest("2.0","/search?q=" + liql?url) />
      <#if (query.status == "success") && query.data.size gt 0>
      	<#return true>
      <#else>
        <#return false>
      </#if>
    </#function>

    and call it like this:

    <#if user.registered && user_has_role(user.id,"'Administrator', 'Developer'")>
    ...
    </#if>

     

    • christiewebb's avatar
      christiewebb
      Guide

      Parshant  This works great for me!  But I would like to also PREVENT a link from showing up for a certain role.  Could you help me with that?  I'm showing Software Notifications to anyone with role "CARRIER_CUSTOMER" - how can I hide Discussions from that same role?

       

      <#function user_has_role (id, roles)>
      <#assign liql = "SELECT id FROM users WHERE roles.name IN (${roles}) and id = '${id}'" />
      <#assign query = rest("2.0","/search?q=" + liql?url) />
      <#if (query.status == "success") && query.data.size gt 0>
      <#return true>
      <#else>
      <#return false>
      </#if>
      </#function>

      <a href="/t5/Discussion/ct-p/discussion">Discussions</a><br>
      <a href="/t5/Product-Notices/ct-p/product-notices-doc">Product Notices</a><br>
      <#if user.registered && user_has_role(user.id,"'Administrator'")>
      <a href="/t5/Software-Notifications/ct-p/software-notifications">Software Notifications</a><br>
      </#if>

      • Parshant's avatar
        Parshant
        Boss

        christiewebb,

        Your code should be,

        <#function user_has_role (id, roles)>
        <#assign liql = "SELECT id FROM users WHERE roles.name IN (${roles}) and id = '${id}'" />
        <#assign query = rest("2.0","/search?q=" + liql?url) />
        <#if (query.status == "success") && query.data.size gt 0>
        <#return true>
        <#else>
        <#return false>
        </#if>
        </#function>
        
        <#if user.registered && user_has_role(user.id,"'CARRIER_CUSTOMER'")>
        <#else>
        <a href="/t5/Discussion/ct-p/discussion">Discussions</a><br>
        </#if>
        <a href="/t5/Product-Notices/ct-p/product-notices-doc">Product Notices</a><br>
        <#if user.registered && user_has_role(user.id,"'CARRIER_CUSTOMER'")>
        <a href="/t5/Software-Notifications/ct-p/software-notifications">Software Notifications</a><br>
        </#if>

         

    • Is there any way where i can avoid making this rest call to fetch roles?? Some predefined function which returns me roles?? 

      • jeffshurtliff's avatar
        jeffshurtliff
        Boss

        diptikaushikkar wrote:

        Is there any way where i can avoid making this rest call to fetch roles?? Some predefined function which returns me roles?? 


        What I do in our environment (which I tailored from the sample code in the blog post How We Built It: Atlas Custom Header by SuzieH) is store our users' roles in the user cache so I only have to perform the REST query every once in a while and then can just reference the user cache going forward.

        For example:

         

        <#-------------------- Function: getUserInfo -------------------->
        <#-- This function aggregates frequently needed user information and stores it in the user cache -->
        <#function getUserInfo force=false refresh=false>
          <#-- Initially define the userInfo data -->
          <#if refresh>
            <#local userInfo = {} />
          <#else>
            <#local userInfo = usercache.get("userInfo")!{} />
          </#if>
          
          <#-- Check to see if there is already valid user info cached -->
          <#if userInfo["valid"]?? && userInfo["valid"] && !force && !refresh>
            <#return userInfo />
          <#else>
            <#-- Get the roles for the user -->
            <#local userRoles = getUserRoles() />
            
            <#-- Add the roles to the userInfo data -->
            <#local userInfo = userInfo + {"roles": userRoles} />
        
            <#-- SNIP -->
        
            <#-- Add the valid flag -->
            <#local userInfo = userInfo + {"valid": true} />
        
            <#-- Return the userInfo data -->
            <#return usercache.put("userInfo", userInfo) />
          </#if>
        </#function>
        
        <#-------------------- Function: getUserRoles -------------------->
        <#-- This function retrieves the roles associated with the user via the API -->
        
        <#function getUserRoles>
          <#if !user.anonymous>
            <#return restadmin("/users/id/${user.id?c}/roles").roles.role />
          <#else>
            <#return [] />
          </#if>
        </#function>

         

        Then it's pretty easy to just recall the user cache in other components as needed.  For example:

         

        <#-- Import the user cache functions -->
        <#include "custom.macro.cache.user.ftl" />
        
        <#-- Retrieve the userInfo data -->
        <#assign userInfo = getUserInfo() />
          
        <#-- Ensure that the user is an employee -->
        <#if userInfo["roles"]?? && userInfo["roles"]?seq_contains("employee")>
          <#-- Do cool stuff here -->
        </#if>

         

        Hope this helps!

  • Something like this should work:

    <#list restadmin("/users/id/${user.id?c}/roles").roles.role as role>
    <#if role.name?? && (role.name == "Administrator")>