accidently deleted 'guest' account, now cannot login

Hi, our version is 15.1.1.3286.

I accidently deleted 'guest' account and now I cannot use imis desktop to login, it complains: 

the application server version may not match the database version.

Browsing imis15 site also generates error:
Asi.Security.UserValidationException: Validation Failed

And idea how to fix this issue?

Thanks.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Recreate GUEST Account script

Run this SQL script in SQL Server Management Studio (or Query Analyzer if you use SQL2K) pointing at your iMIS DB:

-- Create GUEST account if one doesn't already exist
DECLARE @tempID int
DECLARE @tempAddressNum int
DECLARE @now datetime

SET @now = GETDATE()

IF NOT EXISTS (SELECT 1 FROM Name_Security WHERE WEB_LOGIN = 'GUEST')
BEGIN
	SET @tempID = NULL
    SELECT @tempID = ContactMaster FROM UserMain WHERE UserId = 'GUEST'
    IF @tempID IS NULL
    BEGIN
	    EXEC sp_asi_GetCounter Name
	    SELECT @tempID = LAST_VALUE from Counter where COUNTER_NAME = 'Name'
    END
	EXEC sp_asi_GetCounter Name_Address
	SELECT @tempAddressNum = LAST_VALUE from Counter where COUNTER_NAME = 'Name_Address'
	
	INSERT INTO [dbo].[Name] 
           ([ID], [LAST_FIRST], [FIRST_NAME], [FULL_NAME], [MEMBER_TYPE], [STATUS], 
			[MAIL_ADDRESS_NUM], [BILL_ADDRESS_NUM], [SHIP_ADDRESS_NUM],
			[JOIN_DATE], [DATE_ADDED], [LAST_UPDATED], [UPDATED_BY])
	VALUES (CAST(@tempID AS varchar(10)), 'GUEST', 'GUEST', 'GUEST', 'NM', 'A', 
			@tempAddressNum, @tempAddressNum, @tempAddressNum,
			@now, @now, @now, 'MANAGER')

	INSERT Name_Address (ID, ADDRESS_NUM, PURPOSE, PREFERRED_MAIL, PREFERRED_BILL, PREFERRED_SHIP)
	VALUES (CAST(@tempID AS varchar(10)), @tempAddressNum, 'Address', 1, 1, 1)

	INSERT Name_Security (ID, WEB_LOGIN, PASSWORD)
	VALUES (CAST(@tempID AS varchar(10)), 'GUEST', '')

	INSERT Name_Fin (ID) 
	VALUES (CAST(@tempID AS varchar(10)))
END

DECLARE @contactKey uniqueidentifier
DECLARE @contactStatusCode int
DECLARE @managerKey uniqueidentifier 
DECLARE @addressCategoryCode int
DECLARE @accessKey uniqueidentifier 
DECLARE @contactTypeKey uniqueidentifier 
DECLARE @defaultDepartmentGroupKey uniqueidentifier
DECLARE @defaultPerspectiveKey uniqueidentifier
DECLARE @componentKey uniqueidentifier

-- Look-up some required values
SELECT @contactKey = [UserKey] FROM [dbo].[UserMain] WHERE [UserId] = 'GUEST'
IF (@contactKey IS NULL) 
BEGIN
    SELECT @contactKey = [ContactKey] from [dbo].[ContactMain] WHERE [FullName] = 'GUEST'
    IF (@contactKey IS NULL)
        SET @contactKey = newid()
END
SELECT @contactStatusCode = [ContactStatusCode] FROM [dbo].[ContactStatusRef] WHERE [ContactStatusDesc] = 'Active'
SELECT @managerKey = [UserKey] FROM [dbo].[UserMain] WHERE [UserId] = 'MANAGER'
SELECT @addressCategoryCode = [AddressCategoryCode] from [dbo].[AddressCategoryRef] WHERE [AddressCategoryName] = 'Mail'
SELECT @accessKey = [ProtectedAccessKey] FROM [dbo].[AccessArea] WHERE [Name] = 'Everyone Full Control'
SELECT @contactTypeKey = [ContactTypeKey] FROM [dbo].[ContactTypeRef] WHERE [ContactTypeDesc] = 'Individual'
SELECT @defaultDepartmentGroupKey = [GroupKey]
  FROM [dbo].[GroupMain] gm INNER JOIN [dbo].[GroupTypeRef] gt ON gm.GroupTypeKey = gt.GroupTypeKey
 WHERE gm.[Name] = 'Administrative' AND gt.[GroupTypeName] = 'Department'
SELECT @defaultPerspectiveKey = [PerspectiveKey] FROM [dbo].[Perspective] WHERE [PerspectiveName] = 'Administrative'
SELECT @componentKey = [ComponentKey] FROM [dbo].[ComponentRegistry] WHERE [Name] = 'Individual' AND [InterfaceName] = 'BusinessController'

-- Insert into ContactMain if not present
IF NOT EXISTS (SELECT 1 FROM [dbo].[ContactMain] WHERE [FullName] = 'GUEST')
BEGIN
    INSERT INTO [dbo].[UniformRegistry] (UniformKey, ComponentKey) VALUES (@contactKey, @componentKey)
    INSERT INTO [dbo].[ContactMain]
                ([ContactKey], [ContactStatusCode], [FullName], [SortName], [IsInstitute], [NoSolicitationFlag], 
                 [SyncContactID], [UpdatedOn], [UpdatedByUserKey], [IsIDEditable], [ID], [PreferredAddressCategoryCode],
                 [IsSortNameOverridden], [AccessKey], [CreatedByUserKey], [CreatedOn], [TextOnlyEmailFlag],
                 [ContactTypeKey], [OptOutFlag])
    VALUES (@contactKey, @contactStatusCode, 'GUEST', 'GUEST', 0, 0, 
            @tempID, @now, @managerKey, 0, @tempID, @addressCategoryCode, 
            0, @accessKey, @managerKey, @now, 0,
            @contactTypeKey, 0)
END

-- Insert into Individual if not present
IF NOT EXISTS (SELECT 1 FROM [dbo].[Individual] WHERE [FirstName] = 'GUEST')
BEGIN
    INSERT INTO [dbo].[Individual]
                ([ContactKey], [PrefixCode], [FirstName], [MiddleName], [LastName], [SuffixCode], [Designation],
                 [Informal], [Gender])
    VALUES (@contactKey, '', 'GUEST', '', '', '', '', '', '')
END

-- Insert into UserMain if not present
IF NOT EXISTS (SELECT 1 FROM [dbo].[UserMain] WHERE [UserId] = 'GUEST')
BEGIN
    INSERT INTO [dbo].[UserMain]
                ([UserKey], [ContactMaster], [UserId], [IsDisabled], [EffectiveDate], [ExpirationDate],
                 [UpdatedByUserKey], [UpdatedOn], [CreatedByUserKey], [CreatedOn], 
                 [DefaultDepartmentGroupKey], [DefaultPerspectiveKey], [ProviderKey])
    VALUES (@contactKey, @tempID, 'GUEST', 0, '20000101 00:00:00', NULL, @managerKey, @now, @managerKey, @now,
            @defaultDepartmentGroupKey, @defaultPerspectiveKey, NULL)
END
GO

Also, a question...

Also, a question... can you describe how you managed to delete the GUEST account?  We've tried to prevent the software from allowing users to delete this user, so if there's some scenario we've missed, we'd love to hear about it.

Thanks!

 

deleted "Guest" account info

Guest account record showed up when I use search by name: begins with "G" and accidently deleted it as the record only had last name field with GUEST and rest of fields blank.

Record looked same as some of our test record in our database and I simply clicked delete button (I had my delete button option on from customer module).

I wish I have known about "guest" account record and it should have been somehow hidden from search result so that it doesn't bring up GUEST record.

Thank you for above script, but we still have same login error?

 

You will need to recycle the

You will need to recycle the ASP.NET worker process to get it to start working again.

Unfortunately, the legacy code is harder to intercept all the different ways the GUEST record can be deleted, but anything we can do is probably a good idea.

Eric Means
System Architect, ASI

Here is how you fix it

That sucks.  Been there done that...(well one of our clients did). 

Paul/Eric - most people only use classic iMIS and you guys made zero provisions to prevent this.  As you see, you can just click delete on it -or even mark it for deletion and run the purge script from the Utilities Menu - Reports and Queries.  We ended up with a client down for almost a day and they want compensation because WE were the ones who did it ultimately.

Last but not least, your script is not Scottish.  The script below works better.  I seem to remember your script creates some duplicate records in some of the tables.   mjia, remember with our script (Paul/Eric - please pass this one on to support if you approve), you need to set the iMIS ID of the old Guest Account (you can find it in the change log :) )

 

- Fix GUEST account if deleted.  Deleted ID must be set below...  (this line purposely not commented correctly so you don't forget to set the ID below)
-- Only use this script if GUEST was deleted via iMIS
-- Create GUEST account if one doesn't already exist
-- Commit Tran at bottom of script is commented OUT

--See section for update ContactMain "--This has not been tested--"

Begin Tran

ALTER TABLE Name DISABLE TRIGGER asi_Name_Insert_Update

DECLARE @tempID int
DECLARE @tempAddressNum int
DECLARE @now datetime

SET @now = GETDATE()

IF NOT EXISTS (SELECT 1 FROM Name_Security WHERE WEB_LOGIN = 'GUEST')
BEGIN
    SET @tempID = NULL
    SELECT @tempID = ContactMaster FROM UserMain WHERE UserId = 'GUEST'
    IF @tempID IS NULL
    BEGIN
--        EXEC sp_asi_GetCounter Name
--        SELECT @tempID = LAST_VALUE from Counter where COUNTER_NAME = 'Name'

--        Set deleted ID here --
        Select @TempID = '343280'        --Set to old GUEST ID that was deleted--
--        Set deleted ID here --

    END
    EXEC sp_asi_GetCounter Name_Address
    SELECT @tempAddressNum = LAST_VALUE from Counter where COUNTER_NAME = 'Name_Address'
   
    INSERT INTO [dbo].[Name]
           ([ID], [LAST_FIRST], [FIRST_NAME], [FULL_NAME], [MEMBER_TYPE], [STATUS],
            [MAIL_ADDRESS_NUM], [BILL_ADDRESS_NUM], [SHIP_ADDRESS_NUM],
            [JOIN_DATE], [DATE_ADDED], [LAST_UPDATED], [UPDATED_BY])
    VALUES (CAST(@tempID AS varchar(10)), 'GUEST', 'GUEST', 'GUEST', 'NM', 'A',
            @tempAddressNum, @tempAddressNum, @tempAddressNum,
            @now, @now, @now, 'MANAGER')

    INSERT Name_Address (ID, ADDRESS_NUM, PURPOSE, PREFERRED_MAIL, PREFERRED_BILL, PREFERRED_SHIP)
    VALUES (CAST(@tempID AS varchar(10)), @tempAddressNum, 'Address', 1, 1, 1)

    INSERT Name_Security (ID, WEB_LOGIN, PASSWORD)
    VALUES (CAST(@tempID AS varchar(10)), 'GUEST', '')

    INSERT Name_Fin (ID)
    VALUES (CAST(@tempID AS varchar(10)))
END

DECLARE @contactKey uniqueidentifier
DECLARE @contactStatusCode int
DECLARE @managerKey uniqueidentifier
DECLARE @addressCategoryCode int
DECLARE @accessKey uniqueidentifier
DECLARE @contactTypeKey uniqueidentifier
DECLARE @defaultDepartmentGroupKey uniqueidentifier
DECLARE @defaultPerspectiveKey uniqueidentifier
DECLARE @componentKey uniqueidentifier

-- Look-up some required values
SELECT @contactKey = [UserKey] FROM [dbo].[UserMain] WHERE [UserId] = 'GUEST'
IF (@contactKey IS NULL)
BEGIN
    SELECT @contactKey = [ContactKey] from [dbo].[ContactMain] WHERE [FullName] = 'GUEST'
    IF (@contactKey IS NULL)
        SET @contactKey = newid()
END
SELECT @contactStatusCode = [ContactStatusCode] FROM [dbo].[ContactStatusRef] WHERE [ContactStatusDesc] = 'Active'
SELECT @managerKey = [UserKey] FROM [dbo].[UserMain] WHERE [UserId] = 'MANAGER'
SELECT @addressCategoryCode = [AddressCategoryCode] from [dbo].[AddressCategoryRef] WHERE [AddressCategoryName] = 'Mail'
SELECT @accessKey = [ProtectedAccessKey] FROM [dbo].[AccessArea] WHERE [Name] = 'Everyone Full Control'
SELECT @contactTypeKey = [ContactTypeKey] FROM [dbo].[ContactTypeRef] WHERE [ContactTypeDesc] = 'Individual'
SELECT @defaultDepartmentGroupKey = [GroupKey]
  FROM [dbo].[GroupMain] gm INNER JOIN [dbo].[GroupTypeRef] gt ON gm.GroupTypeKey = gt.GroupTypeKey
 WHERE gm.[Name] = 'Administrative' AND gt.[GroupTypeName] = 'Department'
SELECT @defaultPerspectiveKey = [PerspectiveKey] FROM [dbo].[Perspective] WHERE [PerspectiveName] = 'Administrative'
SELECT @componentKey = [ComponentKey] FROM [dbo].[ComponentRegistry] WHERE [Name] = 'Individual' AND [InterfaceName] = 'BusinessController'

-- Insert into ContactMain if not present
IF NOT EXISTS (SELECT 1 FROM [dbo].[ContactMain] WHERE [FullName] = 'GUEST')
BEGIN
    INSERT INTO [dbo].[UniformRegistry] (UniformKey, ComponentKey) VALUES (@contactKey, @componentKey)
    INSERT INTO [dbo].[ContactMain]
                ([ContactKey], [ContactStatusCode], [FullName], [SortName], [IsInstitute], [NoSolicitationFlag],
                 [SyncContactID], [UpdatedOn], [UpdatedByUserKey], [IsIDEditable], [ID], [PreferredAddressCategoryCode],
                 [IsSortNameOverridden], [AccessKey], [CreatedByUserKey], [CreatedOn], [TextOnlyEmailFlag],
                 [ContactTypeKey], [OptOutFlag])
    VALUES (@contactKey, @contactStatusCode, 'GUEST', 'GUEST', 0, 0,
            @tempID, @now, @managerKey, 0, @tempID, @addressCategoryCode,
            0, @accessKey, @managerKey, @now, 0,
            @contactTypeKey, 0)
END

-- Insert into Individual if not present
IF NOT EXISTS (SELECT 1 FROM [dbo].[Individual] WHERE [FirstName] = 'GUEST')
BEGIN
    INSERT INTO [dbo].[Individual]
                ([ContactKey], [PrefixCode], [FirstName], [MiddleName], [LastName], [SuffixCode], [Designation],
                 [Informal], [Gender])
    VALUES (@contactKey, '', 'GUEST', '', '', '', '', '', '')
END

-- Update UserMain to add back ContactMaster and UserID
Update    UserMain
Set        UserId = 'GUEST',
        ContactMaster = @tempID,
        IsDisabled=0
Where    UserKey = @contactKey

--This has not been tested--
Update    ContactMain
Set        SyncContactID = @tempID
Where    ContactKey = @contactKey
--This has not been tested--

--IF NOT EXISTS (SELECT 1 FROM [dbo].[UserMain] WHERE [UserId] = 'GUEST')
--BEGIN
--    INSERT INTO [dbo].[UserMain]
--                ([UserKey], [ContactMaster], [UserId], [IsDisabled], [EffectiveDate], [ExpirationDate],
--                 [UpdatedByUserKey], [UpdatedOn], [CreatedByUserKey], [CreatedOn],
--                 [DefaultDepartmentGroupKey], [DefaultPerspectiveKey], [ProviderKey])
--    VALUES (@contactKey, @tempID, 'GUEST', 0, '20000101 00:00:00', NULL, @managerKey, @now, @managerKey, @now,
--            @defaultDepartmentGroupKey, @defaultPerspectiveKey, NULL)
--END
GO

--------------------------
-- Create provider entries
--------------------------
DECLARE @applicationKey uniqueidentifier
DECLARE @providerKey uniqueidentifier
DECLARE @userID nvarchar(60)
DECLARE @now datetime
DECLARE @beginningOfTime datetime

SET @userID = 'GUEST'
SET @now = GETDATE()
SET @beginningOfTime = '17540101 00:00:00.000'

SELECT @applicationKey = [ApplicationId] FROM [dbo].[aspnet_Applications] WHERE [ApplicationName] = 'iMIS'
SELECT @providerKey = [UserId] FROM [dbo].[aspnet_Users] WHERE [UserName] = @userID
IF (@providerKey IS NULL)
    SET @providerKey = '222953A9-3FB6-4991-9DE9-6DEA4C37D649'
   

IF NOT EXISTS (SELECT 1 FROM [dbo].[aspnet_Users] WHERE [UserName] = @userID)
    INSERT INTO [dbo].[aspnet_Users] ([ApplicationId], [UserId], [UserName], [LoweredUserName], [MobileAlias], [IsAnonymous], [LastActivityDate])
    VALUES (@applicationKey, @providerKey, @userID, LOWER(@userID), NULL, 0, @now)

IF NOT EXISTS (SELECT 1 FROM [dbo].[aspnet_Membership] WHERE [UserId] = @providerKey)
    INSERT INTO [dbo].[aspnet_Membership] ([ApplicationId], [UserId], [Password], [PasswordFormat], [PasswordSalt],
                                           [IsApproved], [IsLockedOut], [CreateDate], [LastLoginDate], [LastPasswordChangedDate], [LastLockoutDate],
                                           [FailedPasswordAttemptCount], [FailedPasswordAttemptWindowStart], [FailedPasswordAnswerAttemptCount], [FailedPasswordAnswerAttemptWindowStart])
    VALUES (@applicationKey, @providerKey, 'Vw/yWCAer8tUkOEucn8mub9hGAU=', 1, 'dH6mEjQq6q6l+/TqIJekqg==',
            0, 0, @now, @now, @now, @beginningOfTime, 0, @beginningOfTime, 0, @beginningOfTime)

UPDATE [dbo].[UserMain]
   SET [ProviderKey] = LOWER(@providerKey)
 WHERE [UserId] = @userID

GO

-------------------------------------------------------------------------------
-- Ensure required Name_Fin, Name_Security, and Name_Security_Groups rows exist
-------------------------------------------------------------------------------
INSERT INTO Name_Fin (ID)
SELECT a.ID FROM Name a LEFT OUTER JOIN Name_Fin b ON a.ID = b.ID
WHERE b.ID IS NULL
GO
INSERT INTO Name_Security (ID)
SELECT a.ID FROM Name a LEFT OUTER JOIN Name_Fin b ON a.ID = b.ID
WHERE b.ID IS NULL
GO
INSERT INTO Name_Security_Groups (ID)
SELECT a.ID FROM Name a LEFT OUTER JOIN Name_Fin b ON a.ID = b.ID
WHERE b.ID IS NULL
GO

ALTER TABLE Name ENABLE TRIGGER asi_Name_Insert_Update

--commit tran
 

How to get the iMIS ID of the old Guest Account?

Thanks Doug.

Can you be more specific about how to get the iMIS ID of the old Guest Account? You said it can be retrieved from change logs, but since I cannot login to imis desktop, how can I see the change logs?

Thanks.

Use Query Analyzer - One of

Use Query Analyzer - One of the following should get you what you need (name_log is not erased and I think either UserMain or Contact main still has it)

Select * from name_log where LOG_TEXT like '%GUEST%'

--ContactMaster has ID
select * FROM UserMain WHERE UserId = 'GUEST'
 
--SyncContactID has ID
select * from ContactMain WHERE FullName = 'GUEST'
 
--
 

found 2 guests accounts now

Hi, I cannot find anything in name_log table.

I found 1 record in UserMain table and I believe it was added by yesterday after I ran the code Paul/Eric provided.

I found 2 records in ContactMain table, one was added by yesterday (contactstatuscode -- 1, SyncContactID -- 21862, ID -- 21862), the other one is old (its contactstatuscode -- 3, SyncContactID -- null, ID -- 19265)

I don't think I can run your code directly (otherwise it will generate another 'guest' account), please let me know how to do.

 

Thanks.

You should have an entry in

You should have an entry in the Name table as well, where ID = the ContactMain.SyncContactID  ... is that not the case?

And can you still not log in?

Name.ID = Name_Security.ID = Name_Fin.ID = ContactMain.SynContactID = UserMain.ContactMaster  ... can you find these coherent records?

There should also be a user name "GUEST" in aspnet_Users, and an associated row in aspnet_Membership where the UserId is the same as the UserId from aspnet_Users.

Does this SQL return any rows?

SELECT a.UserId, a.UserName, a.LastActivityDate, 
       b.Password, b.PasswordFormat, b.IsApproved, b.IsLockedOut, b.CreateDate, b.LastLoginDate 
  FROM aspnet_Users a
       INNER JOIN aspnet_Membership b ON a.UserId = b.UserId
 WHERE a.UserName = 'GUEST'

 Finally, run this query:

SELECT UserKey, ContactMaster, UserId, IsDisabled, EffectiveDate, ExpirationDate, ProviderKey
  FROM UserMain 
 WHERE UserId = 'GUEST'

 In particular, look at the UserId from the aspnet_Users row (from the previous query), and the ProviderKey from the UserMain row (this query)... are they the same?

If you see all the rows present, but the ProviderKey in UserMain is not the same as the UserId in aspnet_Users, then simply update the ProviderKey in UserMain to be equal to the UserId from aspnet_Users.

If any row is missing, you'll need to create that row. 

 

Can login website now but still cannot login to iMIS desktop

I still cannot generate 'Guset' account succesfully. So I restore the database to the one several days ago.

Now I am able to login via the iMIS15 website, but when I try to login iMIS desktop, I got 'OdbcSQL/31 18456 - Logon error -- not a valid Logon or Password' error. Notice that if the password is not input correctly, it reports 'Invalid logon or password' in a popup box immediately. Only if the password is input correctly, it shows this 18456 error.

That's the problem with

That's the problem with their code... :)

It creates two records in the contact main table.   And thus it is not Scottish...

Any chance you have a backup of the db?

That second record is

That second record is deleted, and thus shouldn't be causing problems.  It's essentially orphaned, but shoudln't prevent people from being able to log in.  Running a User Purge from DBRepair should remove it, if it's truly orphaned.

I will update the script I originally posted shortly to be a little smarter (including doing updates if records already exist), though.  Thanks for pointing out the issues!

Paul Then of course you will

Paul

Then of course you will need to test it :)  Delete the guest account (it is easy, really! :), and try your script.  I still say CSI's is better :)

DB restored but logon error

We've restored our backup database,  I can logon to website iMIS15 with manager account, but desktop has error?

showing error: not a valid logon or password?  why?

 

Run DBRepair to recreate the

Run DBRepair to recreate the DB logins.

Eric Means
System Architect, ASI

Block deletion of those accounts

I'm no programmer so this may not be ideal, but couldn't ASI just of add an additional check in thier purge script?  They know the record ID for those accounts, can you add an if record id = 1 or 2 or 3 (whatever those 3 accounts records are) skip to next?  This may fix the issue for anyone using the mark for deletion method, but what about those using the direct delete method?

Next patch/release can ASI add a hidden member type that only manager can edit?  Lets say Admin or Installation, then update the code that doesn't allow anyone, except manager, to edit those records.

RW

15.1.3

In 15.1.3, the GUEST account is protected from deletion and purging.

Guest and Manager Accounts

Hopefully they will do the same for the manager and administrator accounts.

These "service" type accounts should not even be visible to anyone unless they are in an Administrator role.