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 ??

7 Replies

  • Something like this should work:

    <#list restadmin("/users/id/${user.id?c}/roles").roles.role as role>
    <#if role.name?? && (role.name == "Administrator")>
     
  • 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>

     

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

  • Parshant's avatar
    Parshant
    Boss
    5 years ago

    No, there is no other way then this for custom component.

    If you are using in custom page for a category, then you can set the role permission to the whole page.

  • christiewebb's avatar
    christiewebb
    Guide
    5 years ago

    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
    5 years ago

    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>

     

  • jeffshurtliff's avatar
    jeffshurtliff
    Boss
    5 years ago

    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!