9 Removing Staff from Rock Shared by Randy Aufrecht, Community Bible Church-San Antonio 5 years ago 7.0 General Advanced Everyone knows how difficult it is to find all the places where a staff person is a leader of a group, has connections, the main contact of an upcoming event, etc. This is an in depth SQL dynamic data report, a good knowledge of SQL is required. that pulls data from various tables that pertain to different responsibilities a staff person may have had that need to be removed. Some of the SQL statements may need to be adjusted based on your Rock implementation. Each panel lists the Name of the Group (i.e. Security Groups) and the list of the items (i.e. RSR - Rock Administration). Next to each item is either an pencil to edit the item directly, or a sync button because the group may be based on a dataview and the dataview can be edited. Page On the page are 2 blocks a Page Parameter Filter Block and a Dynamic Data Block. The Dynamic Data Block is comprised of 12 different SQL queries all using PersonGuid as the basis for finding their roles. Page Parameter Filter Block This block is a simple block that allows you to filter using page parameters for any values needed, click filter and the page redirects to itself with the PersonAliasGuid in the page parameter that can be read by the dynamic data block. We use this style of filtering for many of our pages. It is a lot cleaner and easier for users to make the correct choices. Block Title Text: Person Filters: Person Name: Person Field Type: Person Key: Person Dynamic Data Block This is the meat and potatoes of the page. The Query section has 12 separate queries. Each one is labeled with what is being queried so you can decide if you need to change it or remove it from your query. -- ===================================================================================================== -- Author: Randy Aufrecht -- Create Date: 7/28/2020 -- Description: Shows various permissions associated with a provided person. -- Taken from https://community.rockrms.com/recipes/80/removing-staff-from-rock -- -- Change History: -- 7/6/2022 Luke Taylor: Updated to get all person aliases not just primary alias, added -- Workflow Assign Activity to Person Actions -- ===================================================================================================== IF @Person != '' DECLARE @PersonId INT = (SELECT [PersonId] FROM [PersonAlias] WHERE [Guid] = @Person ) IF @Person != '' -- 1. Security Groups SELECT g.Id , g.Name AS 'Group' , g.IsActive , g.IsArchived , gs.SyncDataViewId FROM [Group] g INNER JOIN GroupMember gm ON g.id = gm.GroupId AND gm.IsArchived != 1 INNER JOIN GroupType gt ON g.GroupTypeid = gt.Id LEFT JOIN GroupSync gs ON g.Id = gs.GroupId WHERE g.IsSecurityRole = 1 AND gm.[PersonId] = @PersonId ORDER BY g.Name; IF @Person != '' -- 2. Approval Groups | Used for Room Reservation Plugin SELECT g.Id , g.Name AS 'Group' , g.IsActive , g.IsArchived , gs.SyncDataViewId FROM [Group] g INNER JOIN GroupMember gm ON g.id = gm.GroupId AND gm.IsArchived != 1 INNER JOIN GroupType gt ON g.GroupTypeid = gt.Id LEFT JOIN GroupSync gs ON g.Id = gs.GroupId WHERE g.GroupTypeId = 34 AND gm.[PersonId] = @PersonId ORDER BY gt.Name; IF @person != '' -- 3. Connector Groups | The person is in a connector group and could be assigned SELECT g.Id , g.Name AS 'Group' , g.IsActive , g.IsArchived , gs.SyncDataViewId FROM [Group] g INNER JOIN GroupMember gm ON g.id = gm.GroupId AND gm.IsArchived != 1 INNER JOIN GroupType gt ON g.GroupTypeid = gt.Id LEFT JOIN GroupSync gs ON g.Id = gs.GroupId WHERE g.GroupTypeId = 55 AND gm.[PersonId] = @PersonId ORDER BY gt.Name; IF @person != '' -- 4. Group Leadership SELECT g.Id AS 'GroupId' , g.Name AS 'GroupName' , g.IsActive , g.IsArchived FROM [Group] g INNER JOIN GroupMember gm ON g.Id = gm.GroupId AND gm.IsArchived != 1 INNER JOIN GroupTypeRole gtr ON gm.GroupRoleId = gtr.Id AND gtr.IsLeader = 1 WHERE gm.[PersonId] = @PersonId; IF @person != '' -- 5. Default Connector | The person is the default connector for a connection SELECT co.Id , co.ConnectionTypeId , co.Name , c.Name AS 'CampusName' FROM ConnectionOpportunity co INNER JOIN ConnectionOpportunityCampus coc ON co.Id = coc.ConnectionOpportunityId INNER JOIN PersonAlias pa ON coc.DefaultConnectorPersonAliasId = pa.Id AND pa.[PersonId] = @PersonId INNER JOIN Campus c ON coc.CampusId = c.Id ORDER BY co.Name , c.Name; IF @person != '' -- 6. Active Connections | The person has active connections. They should be re-assigned to other people SELECT cr.Id , co.Name AS 'ConnectionOpportunity' , p.NickName + ' ' + p.LastName AS 'PersonName' FROM ConnectionRequest cr INNER JOIN PersonAlias pa ON cr.ConnectorPersonAliasId = pa.Id AND pa.PersonId = @PersonId INNER JOIN ConnectionOpportunity co ON cr.ConnectionOpportunityId = co.Id INNER JOIN PersonAlias pa2 ON cr.PersonAliasId = pa2.Id INNER JOIN Person p ON pa2.PersonId = p.Id WHERE cr.ConnectionState IN (0,2) ORDER BY co.Name , cr.Id; IF @person != '' -- 7. Active Event Contact | This person is an event contact and may be displayed on the website as such. SELECT eio.Id , ei.Name FROM EventItem ei INNER JOIN EventItemOccurrence eio ON ei.Id = eio.EventItemId INNER JOIN Schedule s ON eio.ScheduleId = s.Id AND s.EffectiveEndDate > getdate() INNER JOIN PersonAlias pa ON eio.ContactPersonAliasId = pa.Id AND pa.PersonId = @PersonId WHERE ei.IsActive = 1; IF @person != '' -- 8. Active Registration Contact | This person is a registration contact and may be contacted about registrations. SELECT ri.Id , ri.Name FROM RegistrationInstance AS ri INNER JOIN Registrationtemplate rt ON ri.RegistrationTemplateId = rt.Id INNER JOIN PersonAlias pa ON ri.ContactPersonAliasId = pa.Id AND pa.[PersonId] = @PersonId WHERE ri.IsActive = 1 AND ri.EndDateTime > getdate(); IF @Person != '' -- 9. Org Chart SELECT g.Id , g.Name AS 'Group' , g.IsActive , g.IsArchived , gs.SyncDataViewId FROM [Group] g INNER JOIN GroupMember gm ON g.id = gm.GroupId AND gm.IsArchived != 1 AND gm.[PersonId] = @PersonId INNER JOIN GroupType gt ON g.GroupTypeid = gt.Id LEFT JOIN GroupSync gs ON g.Id = gs.GroupId WHERE g.GroupTypeId = 28 ORDER BY g.Name; IF @Person != '' -- 10. Miscellaneous Security Settings | Various permissions throughout Rock. As I have identified the type of Entity I have joined in the entity table to get enough details to be able to remove the person's permissions SELECT DISTINCT Page.InternalName AS PageName , g.Name AS GroupName , a.EntityTypeId AS EntityType , et.FriendlyName AS EntityName , a.EntityId AS EntityId , rt.Name AS RegName , dv.Name AS Dataview , r.Name AS Report , b.Name AS Block , b.PageId , s.Name AS Schedule FROM Auth a INNER JOIN PersonAlias pa ON a.PersonAliasId = pa.Id AND pa.PersonId = @PersonID INNER JOIN EntityType et ON a.EntityTypeId = et.Id LEFT JOIN Page ON a.EntityId = page.Id AND et.Id = 2 LEFT JOIN [Group] g ON a.EntityId = g.Id AND et.Id = 16 LEFT JOIN RegistrationTemplate rt ON a.EntityId = rt.Id AND et.Id = 234 LEFT JOIN DataView dv ON a.EntityId = dv.Id AND et.Id = 34 LEFT JOIN Report r ON a.EntityId = r.Id AND et.Id = 107 LEFT JOIN Block b ON a.EntityId = b.Id AND et.Id = 9 LEFT JOIN schedule s ON a.EntityId = s.Id AND et.Id = 54 ORDER BY et.FriendlyName; IF @Person != '' -- 11. SMS From Values | This person is attached to SMS numbers that may receive SMS messages. SELECT dv.[Value] , dv.[Description] FROM DefinedValue dv INNER JOIN AttributeValue av ON dv.Id = av.EntityId AND av.AttributeId = 949 INNER JOIN [PersonAlias] pa ON CAST(pa.[Guid] AS NVARCHAR(50)) = av.[Value] AND pa.[PersonId] = @PersonId WHERE DefinedTypeId = 32; IF @Person != '' -- 12. Reservations | Used with the Room Reservation Plugin to identify people who have reserved rooms SELECT r.Id , r.Name FROM _com_centralaz_RoomManagement_Reservation r INNER JOIN PersonAlias pa ON r.EventContactPersonAliasId = pa.Id AND pa.PersonId = @personid IF @Person != '' -- 13. Campus Roles select c.Id , c.Name as CampusName , gtr.Name as RoleName from GroupMember gm inner join GroupTypeRole gtr ON gtr.Id = gm.GroupRoleId inner join Campus c ON c.TeamGroupId = gm.GroupId where gm.PersonId = @PersonId; IF @Person != '' -- 14. Assigned Workflow Activities SELECT wt.[Id] , wt.[Name] AS [WorkflowType] , wact.[Name] AS [Activity] , wacto.[Name] AS [Action] FROM [WorkflowActionType] wacto INNER JOIN [WorkflowActivityType] wact ON wact.[Id] = wacto.[ActivityTypeId] INNER JOIN [WorkflowType] wt ON wt.[Id] = wact.[WorkflowTypeId] INNER JOIN [AttributeValue] av ON av.[EntityId] = wacto.[Id] INNER JOIN [Attribute] a ON a.[Id] = av.[AttributeId] INNER JOIN [PersonAlias] pa ON CAST(pa.[Guid] AS NVARCHAR(50)) = av.[Value] INNER JOIN [Person] p ON p.[Id] = pa.[PersonId] WHERE a.[EntityTypeId] = 115 AND a.[EntityTypeQualifierColumn] = 'EntityTypeId' AND a.[EntityTypeQualifierValue] = '192' AND p.[Id] = @PersonId The Formatted Output iterates through each sql statement in the Query Section and displays the appropriate name and link for editing. {% assign Person2 = 'Global' | PageParameter:'Person' | PersonByAliasGuid %} {% assign Set = 'Global' | PageParameter:'Person' %} {%if Set != '' %} <h2>{{Person2.FullName}}</h2> {%if Person2.Email contains '@oneandall.church' %} {% comment %}This puts an edit person button so you remember to change their profile email address.{% endcomment %} <h3><a href="/Person/{{ Person2.Id}}" class="btn btn-default"><i class="fa fa-pencil"></i></a> Email: {{Person2.Email }}</h3> {% endif %} <br> {% assign numtables = 0 %} <div class="row"> {% comment %} SQL Table 1 - Security Groups{% endcomment %} {% assign results = table1.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Security Groups']} {% for row in table1.rows %} {% if row.SyncDataViewId <> '' and row.SyncDataViewId %} {% capture editurl %}/page/145?DataViewId={{row.SyncDataViewId}}{% endcapture %} {% else %} {% capture editurl %}/page/113?GroupId={{row.Id}}{% endcapture %} {% endif %} <b {%if row.IsActive !=1 or row.IsArchived !=0 %}style="color:Lightgrey;"{% endif %}><a href="{{ editurl }}" class="btn-xs btn-default">{% if row.SyncDataViewId <> '' and row.SyncDataViewId %}<i class="fa fa-sync-alt"></i>{%else%}<i class="fa fa-pencil"></i>{%endif%}</a> {{ row.Group }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% comment %}SQL Table 9 - Orgranization Groups{% endcomment %} {% assign results = table9.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Org Chart']} {% for row in table9.rows %} {% if row.SyncDataViewId <> '' and row.SyncDataViewId %} {% capture editurl %}/page/145?DataViewId={{row.SyncDataViewId}}{% endcapture %} {% else %} {% capture editurl %}/page/113?GroupId={{row.Id}}{% endcapture %} {% endif %} <b {%if row.IsActive !=1 or row.IsArchived !=0 %}style="color:Lightgrey;"{% endif %}><a href="{{ editurl }}" class="btn-xs btn-default">{% if row.SyncDataViewId <> '' and row.SyncDataViewId %}<i class="fa fa-sync-alt"></i>{%else%}<i class="fa fa-pencil"></i>{%endif%}</a> {{ row.Group }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% comment %}SQL Table 4 - Group Leadership{% endcomment %} {% assign results = table4.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Group Leadership']} {% for row in table4.rows %} <b {%if row.IsActive !=1 or row.IsArchived !=0 %}style="color:Lightgrey;"{% endif %}><a href="/page/113?GroupId={{row.GroupId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.GroupName }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 2 - Approval Groups | Used for Room Reservation Plugin{% endcomment %} {% assign results = table2.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Approval Groups']} {% for row in table2.rows %} {% if row.SyncDataViewId <> '' and row.SyncDataViewId %} {% capture editurl %}/page/145?DataViewId={{row.SyncDataViewId}}{% endcapture %} {% else %} {% capture editurl %}/page/113?GroupId={{row.Id}}{% endcapture %} {% endif %} <b {%if row.IsActive !=1 or row.IsArchived !=0 %}style="color:Lightgrey;"{% endif %}><a href="/page/113?GroupId={{row.Id}}" class="btn-xs btn-default">{% if row.SyncDataViewId <> '' and row.SyncDataViewId %}<i class="fa fa-sync-alt"></i>{%else%}<i class="fa fa-pencil"></i>{%endif%}</a> {{ row.Group }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 5 - Connection Opportunity Default | The person is the default connector for a connection{% endcomment %} {% assign results = table5.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Connection Opportunity Default']} {% for row in table5.rows %} <b><a href="/page/411?ConnectionOpportunityId={{row.Id}}&ConnectionTypeId={{row.ConnectionTypeId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Name }} | {{ row.CampusName }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 3 - Connector Groups | The person is in a connector group and could be assigned{% endcomment %} {% assign results = table3.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Connector Groups']} {% for row in table3.rows %} {% if row.SyncDataViewId <> '' and row.SyncDataViewId %} {% capture editurl %}/page/145?DataViewId={{row.SyncDataViewId}}{% endcapture %} {% else %} {% capture editurl %}/page/113?GroupId={{row.Id}}{% endcapture %} {% endif %} <b {%if row.IsActive !=1 or row.IsArchived !=0 %}style="color:Lightgrey;"{% endif %}><a href="/page/113?GroupId={{row.Id}}" class="btn-xs btn-default">{% if row.SyncDataViewId <> '' and row.SyncDataViewId %}<i class="fa fa-sync-alt"></i>{%else%}<i class="fa fa-pencil"></i>{%endif%}</a> {{ row.Group }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 9 - Active Connections | The person has active connections. They should be re-assigned to other people.{% endcomment %} {% assign results = table6.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Active Connections']} {% for row in table6.rows %} <b><a href="/page/408?ConnectionRequestId={{row.Id}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.ConnectionOpportunity }} | {{ row.PersonName }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 7 - Event Contact | This person is an event contact and may be displayed on the website as such.{% endcomment %} {% assign results = table7.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Event Contact']} {% for row in table7.rows %} <b><a href="/page/402?EventItemOccurrenceId={{row.Id}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Name }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 8 - Registration Contact | This person is a registration contact and may be contacted about registrations.{% endcomment %} {% assign results = table8.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Registration Contact']} {% for row in table8.rows %} <b><a href="/RegistrationInstance/{{row.Id}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Name }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 12 - Room Reservations | Used with the Room Reservation Plugin to identify people who have reserved rooms{% endcomment %} {% assign results = table12.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Room Reservations']} {% for row in table12.rows %} <b><a href="/ReservationDetail?ReservationId={{row.Id}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Name }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 11 - SMS From Values | This person is attached to SMS numbers that may receive SMS messages.{% endcomment %} {% assign results = table11.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'SMS From Values']} {% for row in table11.rows %} <b><a href="/page/327" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Value }} | {{ row.Description }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 14 - Assigned Workflow Activties | This person is attached to hard-coded activity assignements.{% endcomment %} {% assign results = table14.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Workflow Activity Assigns']} {% for row in table14.rows %} <b><a href="/page/136?WorkflowTypeId={{ row.[Id }}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.WorkflowType }} | {{ row.Activity }}</b><br> {% endfor %} {[ endpanel ]} </div> {% endif %} {% assign rem = numtables | Modulo:3 %} {% if rem == 0 %} </div> <div class="row"> {% endif %} {% comment %}SQL Table 10 - Miscellaneous Authorizations | Various permissions throughout Rock. As I have identified the type of Entity I have joined in the entity table to get enough details to be able to remove the person's permissions{% endcomment %} {% assign results = table10.rows | Size %} {% if results != 0 %} {% assign numtables = numtables | Plus:1%} <div class="col-md-4"> {[ panel title:'Miscellaneous Authorizations']} {% for row in table10.rows %} {% case row.EntityType %} {% when '2' %} <b><a href="/page/103?Page={{row.EntityId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.PageName }} ({{row.EntityName}})</b><br> {% when '16' %} <b><a href="/page/113?GroupId={{row.EntityId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.GroupName }} ({{row.EntityName}})</b><br> {% when '234' %} <b><a href="/RegistrationInstance/{{row.EntityId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.RegName }} ({{row.EntityName}})</b><br> {% when '34' %} <b><a href="/page/145?DataViewId={{row.EntityId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Dataview }} ({{row.EntityName}})</b><br> {% when '107' %} <b><a href="/page/149?ReportId={{row.EntityId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Report }} ({{row.EntityName}})</b><br> {% when '9' %} <b><a href="/page/103?Page={{row.PageId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Block }} ({{row.EntityName}})</b><br> {% when '54' %} <b><a href="/Schedules?ScheduleId={{row.EntityId}}" class="btn-xs btn-default"><i class="fa fa-pencil"></i></a> {{ row.Schedule }} ({{row.EntityName}})</b><br> {% else %} <b>{{ row.EntityName }}({{row.EntityType}}) | Id:{{row.EntityId}}</b><br> {% endcase %} {% endfor %} {[ endpanel ]} </div> {% endif %} </div> {% else %} <h2>Select a Person Above</h2> {% endif %} Be sure to add Person= to the Parameter field of the Dynamic Data Block. The bottom one named Miscellaneous Authorizations is a list of one-off authorizations that may have been made for that person to view/edit or something else that isn't tied to a security role they were in. This reads the Auth table and contains many different Entity Types. As I have identified them, I have also included the correct links and names for what they have access to. NOTE: the links I used for pages may be specific to each Rock instance as pageId may vary. Make sure you check each url in the formatted output and verify it goes to the correct page in your instance. Download File