Remove sensitive roles from inactive users
Saw this idea and couldn't remember if I shared this already. Basically an endpoint that gets called every day and Loops through a list of roles Finds users with those roles Checks that they're not special accounts, e.g. API user accounts Removes the sensitive roles Per affected user it lists the roles that were removed and the roles that remain Optionally sends a PM to the user to notify them Comments inline. I use Google Apps Script to schedule a daily run, but of course there are other options. Disclaimer: I'm not a trained programmer <#-- Automatically remove roles with permissions from users who haven't logged in for a while --> <#assign user_limit = http.request.parameters.name.get("user_limit", "100")?string /> <#-- How many days must the user have been inactive --> <#assign days_staff = http.request.parameters.name.get("", "50")?number /> <#assign days_mod = http.request.parameters.name.get("", "30")?number /> <#assign send_pm = http.request.parameters.name.get("pm", "false")?boolean /> <#-- Roles to remove from the users we find --> <#assign user_roles_remove = [ "Administrator", "LSI", "Level Two Moderator", "Lithium", "Moderator" ]/> <#-- Some users, like API accounts should be skipped, these are their IDs --> <#assign staff_exceptions = [ 123, 456, 789 ]/> </#if> <#assign users_pm_ids = []/> <#-- Spinning up a sequnce to store the IDs of users we may want to PM about their removed access --> <#assign today_long = .now?date?long/> <#assign prev_long_staff = today_long - days_staff * 1000 * 60 * 60 * 24/> <#assign prev_long_mod = today_long - days_mod * 1000 * 60 * 60 * 24/> <#-- convert the user's last visit date string to the long format for calculation --> <#function fnLVD(lvd)> <#assign lvd_show = lvd?datetime?string["yyyy-MM-dd"]/> <#assign lvd_long = lvd?datetime?long/> <#return lvd_long/> </#function> <xml> <users> <#-- Mods --> <#assign query_mod = restadmin("2.0","/search?q=" + "SELECT id,login,last_visit_time FROM users WHERE roles.name IN('Moderator','Level Two Moderator') LIMIT ${user_limit}"?url)/> <#list query_mod.data.items?sort_by("last_visit_time") as u> <#assign lvd_long = fnLVD(u.last_visit_time)/> <#if (lvd_long < prev_long_mod)> <#assign user_id = u.id/> <#assign user_login = u.login/> <#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/> <#assign user_roles_before = []/> <#list query_user_roles.data.items as r> <#assign role_name = r.name/> <#assign user_roles_before = user_roles_before + [role_name]/> </#list> <#list user_roles_remove as r> <#if (user_roles_before?seq_index_of(r) >= 0)> <#assign result = restadmin("/roles/name/" + r?url + "/users/remove?role.user=id/" + user_id)/> </#if> </#list> <#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/> <#assign user_roles_after = []/> <#list query_user_roles.data.items as r> <#assign role_name = r.name/> <#assign user_roles_after = user_roles_after + [role_name]/> </#list> <user> <login>${user_login}</login> <id>${user_id}</id> <user_type>Moderator</user_type> <roles_removed> <#list user_roles_before as r> <#if (user_roles_after?seq_index_of(r) < 0) && user_roles_remove?seq_index_of(r) >= 0)> <#if (users_pm_ids?seq_index_of(user_id) < 0)> <#assign users_pm_ids = users_pm_ids + [user_id]/> </#if> <role_name>${r}</role_name> </#if> </#list> </roles_removed> <roles_not_removed> <#list roles_remove as r> <#if (user_roles_after?seq_index_of(r) >= 0)> <role_name>${r}</role_name> </#if> </#list> </roles_not_removed> </user> </#if> </#list> <#-- --> <#-- Staff --> <#assign staff_users = []/> <#assign query_staff = restadmin("2.0","/search?q=" + "SELECT id,login,last_visit_time FROM users WHERE roles.name IN('Staff','Administrator','LSI','Lithium') LIMIT ${user_limit}"?url)/> <#list query_staff.data.items?sort_by("last_visit_time") as u> <#assign lvd_long = fnLVD(u.last_visit_time)/> <#if (lvd_long < prev_long_mod)> <#assign user_id = u.id/> <#assign user_login = u.login/> <#assign user_exception = false/> <#list staff_exceptions as s> <#if s?number == user_id?number> <#assign user_exception = true/> <#break> </#if> </#list> <#if user_exception == false> <#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/> <#assign user_roles_before = []/> <#list query_user_roles.data.items as r> <#assign role_name = r.name/> <#assign user_roles_before = user_roles_before + [role_name]/> </#list> <#if (user_roles_before?seq_index_of("Staff") >= 0)> <#assign staff_users = staff_users + [user_id]/> </#if> <#list user_roles_remove as r> <#if (user_roles_before?seq_index_of(r) >= 0)> <#assign result = restadmin("/roles/name/" + r?url + "/users/remove?role.user=id/" + user_id)/> </#if> </#list> <#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/> <#assign user_roles_after = []/> <#list query_user_roles.data.items as r> <#assign role_name = r.name/> <#assign user_roles_after = user_roles_after + [role_name]/> </#list> <user> <login>${user_login}</login> <id>${user_id}</id> <user_type>Admin,Staff</user_type> <roles_removed> <#list user_roles_before as r> <#if (user_roles_after?seq_index_of(r) < 0) && (user_roles_remove?seq_index_of(r) >= 0)> <#if (users_pm_ids?seq_index_of(user_id) < 0)> <#assign users_pm_ids = users_pm_ids + [user_id]/> </#if> <role_name>${r}</role_name> </#if> </#list> </roles_removed> <roles_not_removed> <#list user_roles_remove as r> <#if (user_roles_after?seq_index_of(r) >= 0)> <role_name>${r}</role_name> </#if> </#list> </roles_not_removed> </user> </#if> </#if> </#list> </users> </xml> <#if send_pm == true> <#assign pm_subject = "Your access has been removed"?url/> <#assign pm_body = "<p>Hey! Due to inactivity we have removed some of the more sensitive access from your account.</p><p>If you feel this was in error, please contact the Community Team.</p><p style='margin:40px 0; color:#bbb;font-size:10px'>Please do not reply to this message</p>"?url/> <#list users_pm_ids as u> <#assign result_send = restadmin("/postoffice/notes/send?notes.recipient=/users/id/" + u + "¬es.subject=" + pm_subject + "¬es.note=test")/> </#list> </#if> </#if>596Views5likes0CommentsAurora: Permission descriptions
Each Khoros community permission enables users to perform specific actions. These permissions are assigned (either by default or manually) to different community roles. Permissions are grouped by feature area on the node where you’re assigning them: Accepted Solutions Analytics Badges Blogs Boards Case Portal Categories Community Content Escalations Events Following Groups Ideas Inbox Knowledge Bases Likes Media Member Management Member Profiles Mentions Moderation SEO Tags Widgets A description and a recommendation as to the type of member who should be granted this permission are displayed by each of the permissions so you know exactly what you’re granting and to whom. You can set permissions globally or at the node level (category or board) in the community structure. For each permission, you can keep the out-of-the-box default setting or explicitly Grant or Deny permissions as needed. About permission levels Manage community permission defaults About permission levels Permissions can be set to Inherit, Deny, Grant, or Assign. Inherit – Person has the permission defined in the node or node-level role above the current level. Therefore, this level does not display when you’re managing community permissions defaults but does display for the category, group, and board levels. You can hover your cursor over the Inherit button to see whether the inherited value is Deny or Grant (the button is also displayed as red for Deny and green for Grant). Deny – Person does not have the ability to take action described by the permission. Grant – Person has the ability to take action described by the permission. Assign – Person has the ability to take action described by the permission and has the ability to grant the permission to other members. Typically, this should be given only to Administrator roles. If you look at the Administrator role, you'll notice that all permissions are set to Assign since Admins can grant permissions to other users. As a general rule, only Admins should be able to Assign permissions to others. There are a few use cases where this could change, but typically speaking, Administrators should be the only ones that have the ability to manage permissions in the community. The different permission levels cascade down to any nodes below them, but certain permissions at higher nodes will override lower-node permissions: Assign Overrides any other permissions given at lower-level nodes Explicit Grant Overrides Default Deny, Explicit Deny, and Default Grant at lower-level nodes Explicit Deny Overrides Default Grant and Default Deny but not Explicit Grant at lower-level notes Default Grant Overrides Default Deny but not Explicit Deny at lower-level nodes Default Deny Does not override anything at lower-level nodes Note: If there are conflicts within roles, the explicit exists to override the default. So for example, if you set a permission to Assign at a particular level, all levels below that for that permission will be overridden even if they are set to Deny (including if you manually/explicitly set it to Deny). Note: It is a community management best practice to modify permissions at a role level rather than at a user level to ensure consistency across the community. Manage community permission defaults Setting community permission defaults enables you to grant the base permissions for all members of the community. To manage community permission defaults: Go to Settings > Roles and Permissions. In the Community Permission Defaults section, click Edit. (Optional) To jump to a specific permission to manage, enter it in the Find a permission field. Set Deny or Grant access for the settings in each area. Each permission entry displays a description and recommended deny/grant status, as shown in this example:463Views2likes5CommentsGroup Role vs. Regular Roles
Hi, I'm trying to do something like this, but with group roles: <#assign is_gm = false /> <#list restadmin("/users/id/${user.id?c}/roles").roles.role as role> <#if role.name?? && (role.name == "GroupMember")> <#assign is_gm = true /> Then if it's true or false, I can make the page display accordingly. Apparently this doesn't work for Group Roles though, because it's doesn't recognize GroupMember as a role. So how do I modify it to check whether or not a person has a group role, as opposed to a regular role? Thanks263Views1like4CommentsSelect messages where user *doesn't have* FooBar role?
Objective: Create message list of messages posted by non-employees. SELECT yada, yoda FROM messages WHERE depth = 0 ** AND USER DOESN'T HAVE EMPLOYEE ROLE ** ORDER BY conversation.last_post_time LIMIT 100 From the LiQL reference, I don't see a constraint that will allow this. Is this possible?117Views1like2CommentsAurora: Best practices: roles and permissions
When you first launch a community, permissions and roles are fairly easy to manage because there are a limited number of roles, ranks, and members. As your community grows, you will need to add new ranks and roles to further segment your membership and reward the most active participants. Although you can set individual member permissions one at a time (not recommended), Khoros Communities are designed to help you manage permissions through a hierarchy of roles at the community, category, and board levels. The advantage to this approach, aside from the obvious reduction in the sheer number of moving parts, is a more predictable and manageable permissions structure. The cornerstone of this structure is a link the system creates between roles that have the same name, but that exist at different levels in the community. When you assign roles to members at the community level, they automatically inherit membership in roles that have the same name at the category and board levels. The settings for the new board-level role are stored with those of the higher-level role. Best practices for working with permissions and roles Keep it simple, especially when first launching your community. In the early days of the community, before your active members emerge, you can get by with just a few default roles (Administrator, Moderator, and Khoros or community defaults). At this stage, you want to encourage participation by making it easy for new members to sign in and start posting. You can add roles later as you need them. Set your community-level defaults to the lowest common denominator in terms of access. These defaults apply to all new community members at all levels of the community and are typically the most restrictive settings. As members gain experience in the community and advance up through the ranks, you can give them additional permissions through roles that explicitly grant access. You can always override these defaults with role-based settings at the category or board level. Create roles at the community level, and then create category- or board-level versions of the same roles if you need them. The purpose of a category- or board-level role is to override the community-level settings for a specific category or board. Members who have the community-level role also get the permission settings from the lower-level roles. The names of the roles at all three levels must be exactly the same—including capitalization and spacing—for the connection between roles to work. For example, “Vip” and “VIP” are not the same. The lower-level settings apply only when members are at that level. For example, a category-level permission applies only to members in that category. Elsewhere in the community, community-level permissions are in effect. Always assign roles at the community level rather than at lower levels. This enables you to manage roles and permissions from a single location rather than having to go to each category, for example, and listing the members who have a role assigned to them. Members get the access allowed by the community-wide settings as well as the category-level or board-level override settings for specific categories or boards. The category- or board-level roles typically give members access to areas or features that are off-limits to the rest of the community. Always use roles to assign permissions. The system is designed to track membership in a role, not individual permission settings. As a result, you can easily determine which roles a member has or which members are assigned to the same role. While you cannot assign permissions to individual members, you can look up which roles & permissions are assigned to a particular member (see Look up a member's roles and permissions.) Observe these general tips: Configure permissions and roles to the Principle of Least Privilege. (Apply only the minimum required permissions for a role.) Change permissions within roles only where the default, inherited permission doesn't suffice. For each role, fully document the function of each role, its included permissions, and its purpose and location (for example, if it exists at child levels of community). Provide these details in the role description. Use an informative and consistent naming convention when creating roles. Clear and concise role names make roles much easier to scan and manage and enable new admins to intuit the meaning/purpose of a role.227Views1like4CommentsOOTB component for preview changes link or user menu item
There's a permission that allows you to grant the right to previewing changes on production community. But with this permission granted those users won't see a link to the "Publishing" admin section in their user menu. So two questions: Should users with the preview changes permission see the "Publishing" admin section link in their user menu What's an alternative component to use that would expose the preview link as I cannot easily use this link for preview: /t5/bizapps/page.publishpreviewlinks.link:enterpreviewmodetofrontpage?t:ac=tab/community%3Apublish since a authentication ticket is necessary125Views1like2CommentsDefault bio widget doen't work for plain Users and can't parse it from DB for plain Users
Hi folks. Need the help of the community brain. Found out that the default user bio widget, which parse User description from the settings doesn't work for plain Users except of Admins. So I decided to write my own component to parse that info from DB. Here is the code: <#include "theme-lib.common-variables.ftl" /> <#if user.registered > <#assign qry = "SELECT biography FROM users WHERE id = '${user.id}'"?url /> <#assign res = rest('2.0', '/search?q=${qry}') /> </#if> <@liaAddScript> ;(function() { const messageElement = document.querySelector('.lia-component-article'); if (!messageElement) return; <#if user.registered> <#if ( res.status?matches('success') && (res.data.size > 0) )> <#assign output = res.data.items[0].biography?esc /> const selectors = { main: '.lia-quilt-row-main', wrapper: '.lia-quilt-column-alley-single', ref: '#labelsForMessage', bio: 'custom-widget-user-bios' }; const parent = messageElement.querySelector(selectors.main + ' ' + selectors.wrapper); const refEl = messageElement.querySelector(selectors.ref); let p = document.createElement('p'); p.classList.add(selectors.bio); p.textContent = '${output}'; console.log(messageElement, refEl) parent.insertBefore(p, refEl); </#if> </#if> }()); </@liaAddScript> It Does work with Admins, but again, does not work with plain Users somewhy. It throw an exception in the console: <div style="font-style: italic; font-weight: lighter; color: darkGrey; background-color: Beige; padding: 10px;" class="lia-widget-not-found"> This widget could not be displayed. </div> Help me pls, what's going wrong with that user bio widget and Data i wanna parse it to the view by myself. Also I didn't find any flag in the admin that could representatively control that feature and enable/disable it.625Views1like3Comments