7
votes

I'm fully aware that deleting users (SystemUser Entity) in CRM Dynamics 2011 is not supported by Microsoft.

However, we're currently developing a tool to support our User Provisioning needs. In order to be able to write integration tests for this tool, it seems necessary to be able to remove users afterwards, so that we can rollback our test environment to the original state.
Currently, we're doing this by restoring organizations from SQL backups, but this is too time consuming to do for each test run.

Update

So far, the best solution we have is to create a user in the integration test, assert everything we need to assert, and afterwards "clean it up" by disabling the user and removing its AD credentials, so that we can re-use those credentials for the next run of the test.

However, as we're only looking for a solution for a test environment, I would really like to have a solution that cleans everything up properly: deleting the records in SQL seems like the way to go. Due to the complex DB structure, however, I was hoping that someone could provide scripts for this.

Update2

We've created the script to manually delete the user from SQL (see accepted answer). This is not supported, so only use it in test environments, if you know what you're doing.

6
why not just disable the users?Guido Preite
@GuidoPreite Because we are testing software that is built around inserting new users. If we disable them, we still can't reuse the user account to insert it again.Joris Van Regemortel

6 Answers

10
votes

The following script is not supported by Microsoft. Using it might harm, brick, blow up or molest your CRM organization, deployment, server and career.
Never use this.
Ever.

That being said, we used this, and it worked fine for our purpose: cleaning up our test environment after running AddSystemUser tests.

Some other things to keep in mind :

  • We are using CRM Dynamics 2011 UR10 On-Premises
  • Our test user doesn't have any related records, it's just an isolated user
  • We're using AD authentication
USE OrganizationName_MSCRM
BEGIN TRANSACTION
DECLARE @username AS VARCHAR(50)

-- CHANGE THIS -- 
SET @username = 'domain\username'
-- DONT CHANGE ANYTHING AFTER THIS --

DECLARE @userId AS UNIQUEIDENTIFIER
SET @userId = (SELECT SystemUserId  FROM dbo.SystemUserBase WHERE DomainName = @username)

DECLARE @orgid AS UNIQUEIDENTIFIER
SET @orgid = (SELECT OrganizationId FROM dbo.SystemUserBase WHERE systemuserid = @userid)

DECLARE @userEmail AS VARCHAR(MAX)
SET @useremail = (SELECT InternalEMailAddress FROM dbo.SystemUserBase WHERE SystemUserId = @userid)

DECLARE @userfullname AS VARCHAR(max)
SET @userfullname = (SELECT fullname FROM dbo.systemuserbase WHERE systemuserid = @userid)

DECLARE @queueid AS UNIQUEIDENTIFIER
SET @queueid = (SELECT queueid FROM dbo.SystemUserBase WHERE SystemUserId = @userid)

DECLARE @ownerid AS UNIQUEIDENTIFIER
SET @ownerid = (SELECT ownerid FROM dbo.OwnerBase WHERE name = @userfullname)

DELETE FROM dbo.SystemUserExtensionBase WHERE SystemUserId = @userId
DELETE FROM dbo.UserSettingsBase WHERE SystemUserId = @userId
DELETE FROM dbo.TeamMembership WHERE SystemUserId = @userId
DELETE FROM dbo.SystemUserPrincipals WHERE systemuserid = @userId
DELETE FROM dbo.SystemUserRoles WHERE systemuserid = @userId
DELETE FROM dbo.SystemUserBusinessUnitEntityMap WHERE systemuserid = @userid
DELETE FROM dbo.UserQueryBase WHERE OwnerId = @userid
DELETE FROM dbo.SystemUserProfiles WHERE SystemUserId = @userId
DELETE FROM dbo.SystemUserBase WHERE SystemUserId = @userid
DELETE FROM dbo.QueueBase WHERE QueueId = @queueid
DELETE FROM dbo.PrincipalEntityMap WHERE PrincipalId = @ownerid
DELETE FROM dbo.PrincipalObjectAccess WHERE principalid = @ownerid
DELETE FROM dbo.OwnerBase WHERE ownerid = @ownerid
DELETE FROM dbo.EmailSearchBase WHERE EmailAddress = @userEmail
DELETE FROM dbo.ResourceBase WHERE name = @userfullname
DELETE FROM dbo.CalendarRuleBase WHERE CalendarId IN (SELECT CalendarId FROM dbo.CalendarBase WHERE PrimaryUserId = @userid)
DELETE FROM dbo.CalendarBase WHERE primaryuserid = @userId
DELETE FROM dbo.InternalAddressBase WHERE parentid = @userId

DELETE FROM mscrm_config..SystemUserOrganizations WHERE CrmUserId = @userid AND OrganizationId = @orgid

COMMIT
2
votes

Maybe you can try this work around. Rather than just disabling them, change the active directory name to something else, then disable the records.

For example, your script could look as follows (assuming AD authentication):

Create AD users msmith, bmiller, and jdoe.

Perform tests and validation.

Update msmith to testuser1
Update bmiller to testuser2
Update jdoe to testuser3

Deactivate testuser1, testuser2, testuser3

Next test will need to use testuser4, testuser5, testuser6, which means you'll need to create quite a few dummy accounts, but it may be easier to do that, than mess with the CRM SQL database.

For my unit tests where I need a User, I actually mock out the IOrganizationService call for just SystemUser requests, and return a mocked SystemUser entity without it actually hitting CRM. I would suggest that as well, but it sounds like you're attempting to actually test System User creation, so probably isn't an option in this case.

2
votes

Here is what I have done in CRM 2015 based on Joris code

USED ORGANIZATIONNAME_MSCRM

BEGIN TRANSACTION

DECLARE @username AS VARCHAR(50)



-- CHANGE THIS --

SET @username = 'AD\USERNAME'

-- DONT CHANGE ANYTHING AFTER THIS --



DECLARE @userId AS UNIQUEIDENTIFIER

SET @userId = (SELECT SystemUserId  FROM dbo.SystemUserBase WHERE DomainName = @username)



DECLARE @orgid AS UNIQUEIDENTIFIER

SET @orgid = (SELECT OrganizationId FROM dbo.SystemUserBase WHERE systemuserid = @userid)



DECLARE @userEmail AS VARCHAR(MAX)

SET @useremail = (SELECT InternalEMailAddress FROM dbo.SystemUserBase WHERE SystemUserId = @userid)



DECLARE @userfullname AS VARCHAR(max)

SET @userfullname = (SELECT fullname FROM dbo.systemuserbase WHERE systemuserid = @userid)



DECLARE @queueid AS UNIQUEIDENTIFIER

SET @queueid = (SELECT queueid FROM dbo.SystemUserBase WHERE SystemUserId = @userid)



DECLARE @ownerid AS UNIQUEIDENTIFIER

SET @ownerid = (SELECT ownerid FROM dbo.OwnerBase WHERE name = @userfullname)



DECLARE @MSCRMUserID as UNIQUEIDENTIFIER

SET @MSCRMUserID = (SELECT Userid FROM mscrm_config..SystemUserOrganizations WHERE CrmUserId = @userid AND OrganizationId = @orgid)

DECLARE @authinfo as NVARCHAR(255)

SET @authinfo = (SELECT Authinfo FROM mscrm_config..SystemUserAuthentication WHERE Userid = @MSCRMUserID)

DECLARE @SUid as UNIQUEIDENTIFIER

SET @Suid = (SELECT id FROM mscrm_config..SystemUserAuthentication WHERE Userid = @MSCRMUserID)



DELETE FROM dbo.UserSettingsBase WHERE SystemUserId = @userId

DELETE FROM dbo.TeamMembership WHERE SystemUserId = @userId

DELETE FROM dbo.SystemUserPrincipals WHERE SystemUserId = @userId

DELETE FROM dbo.SystemUserRoles WHERE SystemUserId = @userId

DELETE FROM dbo.SystemUserBusinessUnitEntityMap WHERE systemuserid = @userid

DELETE FROM dbo.UserQueryBase WHERE OwnerId = @userid

DELETE FROM dbo.SystemUserProfiles WHERE SystemUserId = @userId

DELETE FROM dbo.TeamMembership WHERE SystemUserId = @userId



DELETE FROM dbo.QueueMembership  WHERE SystemUserId = @userId

DELETE FROM dbo.SystemUserBase WHERE SystemUserId = @userid

DELETE FROM dbo.QueueBase WHERE QueueId = @queueid



DELETE FROM dbo.PrincipalEntityMap WHERE PrincipalId = @ownerid

DELETE FROM dbo.PrincipalObjectAccess WHERE PrincipalId = @ownerid

DELETE FROM dbo.MailboxBase WHERE OwnerId = @ownerid

DELETE FROM dbo.OwnerBase WHERE OwnerId = @ownerid

DELETE FROM dbo.EmailSearchBase WHERE EmailAddress = @userEmail

DELETE FROM dbo.ResourceBase WHERE name = @userfullname

DELETE FROM dbo.CalendarRuleBase WHERE CalendarId IN (SELECT CalendarId FROM dbo.CalendarBase WHERE PrimaryUserId = @userid)

DELETE FROM dbo.InternalAddressBase WHERE parentid = @userId

DELETE FROM dbo.CalendarBase WHERE primaryuserid = @userId



DELETE FROM mscrm_config..SystemUserOrganizations WHERE CrmUserId = @userid AND OrganizationId = @orgid

DELETE FROM mscrm_config..SystemUserAuthentication WHERE authinfo = @authinfo

DELETE FROM mscrm_config..SystemUser WHERE id = @MSCRMUserID



rollback

--COMMIT

Once you have run the query and made sure it is deleting the right data, you can un-comment the COMMIT statement and comment the Rollback statement

Hope it helps.

2
votes

Just some slight modifications for Dynamics CRM 2016 (On Premise) to allow for some common constraint errors that I came across. Again, this is completely non-supported and proceed at your own risk. (I will update when I find other constraint errors.)

BEGIN TRANSACTION
DECLARE @username AS VARCHAR(50)
/* CHANGE THIS LINE ONLY */
SET @username = 'DOMAIN\USERNAME'
/* END CHANGES */
DECLARE @userId AS UNIQUEIDENTIFIER
SET @userId = (SELECT SystemUserId  FROM dbo.SystemUserBase WHERE DomainName = @username)
DECLARE @orgid AS UNIQUEIDENTIFIER
SET @orgid = (SELECT OrganizationId FROM dbo.SystemUserBase WHERE systemuserid = @userid)
DECLARE @userEmail AS VARCHAR(MAX)
SET @useremail = (SELECT InternalEMailAddress FROM dbo.SystemUserBase WHERE SystemUserId = @userid)
DECLARE @userfullname AS VARCHAR(max)
SET @userfullname = (SELECT fullname FROM dbo.systemuserbase WHERE systemuserid = @userid)
DECLARE @queueid AS UNIQUEIDENTIFIER
SET @queueid = (SELECT queueid FROM dbo.SystemUserBase WHERE SystemUserId = @userid)
DECLARE @ownerid AS UNIQUEIDENTIFIER
SET @ownerid = (SELECT ownerid FROM dbo.OwnerBase WHERE name = @userfullname)
DECLARE @MSCRMUserID as UNIQUEIDENTIFIER
SET @MSCRMUserID = (SELECT Userid FROM mscrm_config..SystemUserOrganizations WHERE CrmUserId = @userid AND OrganizationId = @orgid)
DECLARE @authinfo as NVARCHAR(255)
SET @authinfo = (SELECT Authinfo FROM mscrm_config..SystemUserAuthentication WHERE Userid = @MSCRMUserID)
DECLARE @SUid as UNIQUEIDENTIFIER
SET @Suid = (SELECT id FROM mscrm_config..SystemUserAuthentication WHERE Userid = @MSCRMUserID)
DELETE FROM dbo.UserSettingsBase WHERE SystemUserId = @userId
DELETE FROM dbo.TeamMembership WHERE SystemUserId = @userId
DELETE FROM dbo.SystemUserPrincipals WHERE SystemUserId = @userId
DELETE FROM dbo.SystemUserRoles WHERE SystemUserId = @userId
DELETE FROM dbo.SystemUserBusinessUnitEntityMap WHERE systemuserid = @userid
DELETE FROM dbo.UserQueryBase WHERE OwnerId = @userid
DELETE FROM dbo.SystemUserProfiles WHERE SystemUserId = @userId
DELETE FROM dbo.TeamMembership WHERE SystemUserId = @userId
DELETE FROM dbo.QueueMembership  WHERE SystemUserId = @userId
update dbo.SdkMessageFilterBase set ModifiedOnBehalfBy = NULL where ModifiedOnBehalfBy = @userid
update dbo.SdkMessageFilterBase set CreatedOnBehalfBy = NULL where CreatedOnBehalfBy = @userid
DELETE FROM dbo.SystemUserBase WHERE SystemUserId = @userid
DELETE FROM dbo.CalendarRuleBase WHERE CalendarId IN (SELECT CalendarId FROM dbo.CalendarBase WHERE PrimaryUserId = @userid)
DELETE FROM dbo.CalendarBase WHERE primaryuserid = @userId
DELETE FROM dbo.QueueBase WHERE QueueId = @queueid
DELETE FROM dbo.PrincipalEntityMap WHERE PrincipalId = @ownerid
DELETE FROM dbo.PrincipalObjectAccess WHERE PrincipalId = @ownerid
DELETE FROM dbo.UserEntityUISettingsBase WHERE OwnerID = @userid
DELETE FROM dbo.UserApplicationMetadataBase WHERE OwnerID = @userid
DELETE FROM dbo.PostFollowBase WHERE OwnerID = @userid
DELETE FROM dbo.MailboxBase WHERE OwnerId = @ownerid
DELETE FROM dbo.OwnerBase WHERE OwnerId = @ownerid
DELETE FROM dbo.EmailSearchBase WHERE EmailAddress = @userEmail
DELETE FROM dbo.ResourceBase WHERE name = @userfullname
DELETE FROM dbo.InternalAddressBase WHERE parentid = @userId
DELETE FROM mscrm_config..SystemUserOrganizations WHERE CrmUserId = @userid AND OrganizationId = @orgid
DELETE FROM mscrm_config..SystemUserAuthentication WHERE authinfo = @authinfo
DELETE FROM mscrm_config..SystemUser WHERE id = @MSCRMUserID
/* rollback */
COMMIT
1
votes

You could use the totally unsupported way of deleting them by SQL.
As long as you're doing this in an integration test environment I think the harm would be relatively low.

To find what changes are made in the database when adding a user you could

  • copy your current database
  • add a user
  • compare new database state with the previous one (e.g: redgate's SQL compare)

It could be this changes with each rollup so be sure to not rely on this for anything critical or production code.

0
votes

This isn't supported, but how about deleting the records directly from SQL?

Never tried it myself and I wouldn't want to do it on a production environment, but if its just for testing/development the worst that happens is you trash a development environment.