/// <summary> /// REMOVE an undesired user from a group /// </summary> /// <param name="siteSignIn"></param> /// <param name="userRemoveFromGroup"></param> /// <param name="siteGroup"></param> private void Execute_ProvisionGroups_RemoveSingleUser(TableauServerSignIn siteSignIn, SiteUser userRemoveFromGroup, SiteGroup siteGroup) { _statusLogs.AddStatus("Attempting to remove the user " + userRemoveFromGroup.Name + " from group " + siteGroup.Name); switch (_provisionInstructions.ActionForUnexpectedGroupMembers) { case ProvisionUserInstructions.UnexpectedGroupMemberAction.Delete: var deleteUserFromGroup = new SendDeleteUserFromGroup(siteSignIn, userRemoveFromGroup.Id, siteGroup.Id); bool wasSuccess = deleteUserFromGroup.ExecuteRequest(); if (wasSuccess) { //SUCCESS CSVRecord_GroupModified_WithUser(siteGroup.Name, "removed member", userRemoveFromGroup.Name, ""); _statusLogs.AddStatus("Group membership: Removed " + userRemoveFromGroup.Name + " from group " + siteGroup.Name); } else { CSVRecord_Error(userRemoveFromGroup.Name, "", "", "User could not be removed to group " + siteGroup.Name); _statusLogs.AddError("Group membership error: Failed to remove " + userRemoveFromGroup.Name + " to group " + siteGroup.Name); } return; case ProvisionUserInstructions.UnexpectedGroupMemberAction.Report: //We are instructed to NOT REALLY DELETE the user from the group, jsut report CSVRecord_GroupModified_WithUser(siteGroup.Name, "SIMULATED removed member", userRemoveFromGroup.Name, ""); return; default: IwsDiagnostics.Assert(false, "814-433: Unknown action"); throw new Exception("814-433: Unknown action"); } }
/// <summary> /// For this type of content, change the ownership from one user to another /// </summary> /// <param name="siteSignIn"></param> /// <param name="thisOwnershipChange"></param> /// <param name="userOldOwner"></param> /// <param name="userNewOwner"></param> private void Execute_ProvisionOwnership_SingleUserChange_Workbooks(TableauServerSignIn siteSignIn, SiteUser userOldOwner, SiteUser userNewOwner) { //Get the list of workbooks (if any) owned by the old user var inventoryDownloader = new DownloadWorkbooksList(siteSignIn, userOldOwner.Id, true); inventoryDownloader.ExecuteRequest(); var listContent = inventoryDownloader.Workbooks; if ((listContent == null) || (listContent.Count < 1)) { _statusLogs.AddStatus("No work to do. No workbooks owned by: " + userOldOwner.Name); return; } //Change the ownership of each of these content items foreach (var contentItem in listContent) { if (string.Compare(contentItem.OwnerId, userOldOwner.Id, true) == 0) { Execute_ProvisionOwnership_SingleUserChange_SingleWorkbook(siteSignIn, contentItem, userOldOwner, userNewOwner); } else { IwsDiagnostics.Assert(false, "201202-607: Expected not to have content not owned by user"); } } }
/// <summary> /// Get the user's email from the Graph API's User object /// </summary> /// <param name="graphUser"></param> /// <returns></returns> private string GetUserEmailFromGraphADUser(Microsoft.Graph.User graphUser) { string emailCandidate; switch (_configSyncGroups.EmailMapping) { //Use the name of the principal in AzureAD case ProvisionConfigExternalDirectorySync.UserEmailMapping.UserPrincipalName: emailCandidate = graphUser.UserPrincipalName; IwsDiagnostics.Assert(!string.IsNullOrWhiteSpace(emailCandidate), "814-705: User principal name is NULL"); return(emailCandidate.Trim()); //If the user has another email address listed, use it case ProvisionConfigExternalDirectorySync.UserEmailMapping.PreferAzureProxyPrimaryEmail: emailCandidate = GetUserEmailFromGraphADUser_TryPrimaryProxyEmailLookup(graphUser); //If no email candidate was found, use the principal name if (string.IsNullOrWhiteSpace(emailCandidate)) { emailCandidate = graphUser.UserPrincipalName; IwsDiagnostics.Assert(!string.IsNullOrWhiteSpace(emailCandidate), "1009-1210: User principal name is NULL"); } return(emailCandidate.Trim()); default: //Unknown mode IwsDiagnostics.Assert(false, "1009-1208: Unknown user email mapping mode"); throw new Exception("1009-1208: Unknown user email mapping mode"); } }
/// <summary> /// Remove an existing user /// </summary> /// <param name="userEmail"></param> /// <returns></returns> public bool RemoveUser(string userEmail) { string cannonicalKey = CannonicalKey(userEmail); //See if the user is already in our list ProvisioningUser existingUser = null; if (!_allUsersSet.TryGetValue(cannonicalKey, out existingUser)) { return(false); } //======================================================================= //We need to remove the old user //======================================================================= bool wasRemoved; //Remove wasRemoved = _allUsersSet.Remove(cannonicalKey); IwsDiagnostics.Assert(wasRemoved, "814-200: Internal error, item not found"); //Remove wasRemoved = GetManagerForRole(existingUser.UserRole).RemoveUser(cannonicalKey); IwsDiagnostics.Assert(wasRemoved, "814-200: Internal error, item not found"); return(wasRemoved); }
/* * public static string ApplicationTitle * { * get * { * return "UNDONE: TEMP TITLE"; * } * } */ /// <summary> /// Looks up an attribute by name and returns true/false /// </summary> /// <param name="attributeName"></param> /// <param name="defaultValue"></param> /// <returns></returns> private static bool GetAppSettingIntegerBoolean(string attributeName, bool defaultValue) { IwsDiagnostics.Assert(!string.IsNullOrWhiteSpace(attributeName), "160615-1959, missing attribute name"); var textValue = ConfigurationManager.AppSettings[attributeName]; if (string.IsNullOrWhiteSpace(textValue)) { return(defaultValue); } textValue = textValue.Trim().ToLower(); if (textValue == "true") { return(true); } if (textValue == "false") { return(false); } //Abort IwsDiagnostics.Assert( false, "160615-1958, attribute value not true/false, " + attributeName + "/" + textValue); throw new ArgumentException("160615-1958, attribute value not true/false, " + attributeName + "/" + textValue); }
/// <summary> /// Get the user's email from the Graph API's User object /// </summary> /// <param name="graphUser"></param> /// <returns></returns> private string GetUserEmailFromGraphADUser(Microsoft.Graph.User graphUser) { string emailCandidate = graphUser.UserPrincipalName; IwsDiagnostics.Assert(!string.IsNullOrWhiteSpace(emailCandidate), "814-705: User principal name is NULL"); return(emailCandidate.Trim()); }
/// <summary> /// Update the provisioning status for a single unexpected user /// </summary> /// <param name="unexpectedUser"></param> /// <param name="siteSignIn"></param> private void Execute_UpdateUnexpectedUsersProvisioning_SingleUser( SiteUser unexpectedUser, TableauServerSignIn siteSignIn, WorkingListSiteUsers workingList_allKnownUsers) { _statusLogs.AddStatus("Process unexpected user: "******"811-1123: Unknown authentication type " + unexpectedUser.SiteAuthentication + ", for user " + unexpectedUser.Name); _statusLogs.AddError("811-1123: Unknown authentication type " + unexpectedUser.SiteAuthentication + ", for user " + unexpectedUser.Name); break; } }
/// <summary> /// Add a user to our tracking list /// </summary> /// <param name="tableauRole"></param> /// <param name="graphUser"></param> private void AddUserToRoleProvisioningTrackingManager_Inner(string tableauRole, bool allowPromotedRole, string authModel, Microsoft.Graph.User graphUser, string sourceGroupName) { string emailCandidate = GetUserEmailFromGraphADUser(graphUser); IwsDiagnostics.Assert(!string.IsNullOrWhiteSpace(emailCandidate), "813-326: User principal name is NULL"); //Add the user to our tracking set SetManagerForRoles.AddUser(new ProvisioningUser(emailCandidate, tableauRole, authModel, sourceGroupName, allowPromotedRole)); }
/// <summary> /// Add the user to the tracking object /// </summary> /// <param name="targetGroupName"></param> /// <param name="graphUser"></param> /// <param name="sourceGroupName"></param> private void AddUserToGroupProvisioningTrackingManager_Inner(string targetGroupName, Microsoft.Graph.User graphUser, ProvisionConfigExternalDirectorySync.SynchronizeGroupToGroup targetGroup) { string emailCandidate = GetUserEmailFromGraphADUser(graphUser); IwsDiagnostics.Assert(!string.IsNullOrWhiteSpace(emailCandidate), "843-706: User principal name is NULL"); //Add the user to our tracking set SetManagerForGroups.AddUserToGroup(targetGroup, emailCandidate); }
/// <summary> /// Add a user to specified Group /// </summary> /// <param name="groupSyncInstructions"></param> /// <param name="singleGroupMembershipManager"></param> /// <param name="graphUser"></param> private void AddUserToGroupProvisioningTrackingManager( ProvisionFromDirectoryGroupsMembershipManager.SingleGroupManager singleGroupMembershipManager, Microsoft.Graph.User graphUser) { string emailCandidate = GetUserEmailFromGraphADUser(graphUser); IwsDiagnostics.Assert(!string.IsNullOrWhiteSpace(emailCandidate), "843-706: User principal name is NULL"); singleGroupMembershipManager.AddUser(emailCandidate); }
/// <summary> /// Load app preferences that we want to auto-load next time /// </summary> private void AppPreferences_Load() { try { AppPreferences_Load_Inner(); } catch (Exception ex) { IwsDiagnostics.Assert(false, "819-1041: Error loading app prefernces, " + ex.Message); } }
/// <summary> /// Store app preferences that we want to auto-load next time /// </summary> private void AppPreferences_Save() { try { AppPreferences_Save_Inner(); } catch (Exception ex) { IwsDiagnostics.Assert(false, "819-1014: Error storing app prefernces, " + ex.Message); } }
/// <summary> /// Saves a string from the Windows registry (load a user preference) /// </summary> /// <param name="preferenceName"></param> /// <param name="value"></param> private static string LoadRegistryString(string preferenceName) { try { //Get the value as a string return((string)Registry.GetValue(Registry_AppKey, preferenceName, "")); } catch (Exception ex) { IwsDiagnostics.Assert(false, "819-1040: Error loading registry value, " + preferenceName + ", " + ex.Message); return(""); } }
/// <summary> /// Handle the provisioning for a single user /// </summary> /// <param name="userToProvision"></param> /// <param name="siteSignIn"></param> /// <param name="workingListUnexaminedUsers"></param> private void Execute_ProvisionUsers_SingleUser( ProvisioningUser userToProvision, TableauServerSignIn siteSignIn, WorkingListSiteUsers workingListUnexaminedUsers) { //See if a user with this name already exists var foundExistingUser = workingListUnexaminedUsers.FindUser(userToProvision.UserName); ProvisionUserInstructions.MissingUserAction missingUserAction; ProvisionUserInstructions.UnexpectedUserAction unexpectedUserAction; //Get the instructions based on the desired Auth model for the user we are provisioning switch (userToProvision.UserAuthenticationParsed) { case SiteUserAuth.Default: missingUserAction = _provisionInstructions.ActionForMissingDefaultAuthUsers; unexpectedUserAction = _provisionInstructions.ActionForUnexpectedDefaultAuthUsers; break; case SiteUserAuth.SAML: missingUserAction = _provisionInstructions.ActionForMissingSamlUsers; unexpectedUserAction = _provisionInstructions.ActionForUnexpectedSamlUsers; break; default: IwsDiagnostics.Assert(false, "814-1204: Unknown auth type"); throw new Exception("814-1204: Unknown auth type"); } //CASE 1: The user does NOT exist. So add them if (foundExistingUser == null) { Execute_ProvisionUsers_SingleUser_AddUser(siteSignIn, userToProvision, missingUserAction); return; } //CASE 2: The user EXISTS but is not the right role or auth; update them if ( (string.Compare(foundExistingUser.SiteRole, userToProvision.UserRole, true) != 0) || (string.Compare(foundExistingUser.SiteAuthentication, userToProvision.UserAuthentication, true) != 0) ) { Execute_ProvisionUsers_SingleUser_ModifyUser(siteSignIn, userToProvision, foundExistingUser); return; } //CASE 3: The user exists and does NOT need to be modified _statusLogs.AddStatus("No action: User exists and has expected role and authentication. User: " + userToProvision.UserName); }
/// <summary> /// Parse the Grant license text returned /// </summary> /// <param name="text"></param> /// <returns></returns> ProvisioningGroup.GrantLicenseMode AttemptParseGrantLicenseText(string text) { //var parseGrantLicenseMode ProvisioningGroup.GrantLicenseMode grantLicenseMode = ProvisioningGroup.GrantLicenseMode.Ignore; try { return(ProvisioningGroup.ParseGrantLicenseModeFromTableauServer(text)); } catch (Exception ex) { //Note the error -- but it is not fatal for our purposes IwsDiagnostics.Assert(false, "1012-528: Unknown grant license mode parsing error, " + ex.Message); return(grantLicenseMode); } }
/// <summary> /// XML Serialization value /// </summary> /// <param name="action"></param> /// <returns></returns> internal static string XmlAttributeText(ExistingUserAction action) { switch (action) { case ExistingUserAction.Modify: return(AttributeValue_Modify); case ExistingUserAction.Report: return(AttributeValue_Report); default: IwsDiagnostics.Assert(false, "814-248: Internal error, missing value"); throw new Exception("814-248: Internal error, missing value"); } }
/// <summary> /// XML Serialization value /// </summary> /// <param name="action"></param> /// <returns></returns> internal static string XmlAttributeText(UnexpectedGroupMemberAction action) { switch (action) { case UnexpectedGroupMemberAction.Delete: return(AttributeValue_Delete); case UnexpectedGroupMemberAction.Report: return(AttributeValue_Report); default: IwsDiagnostics.Assert(false, "814-413: Internal error, missing value"); throw new Exception("814-413: Internal error, missing value"); } }
/// <summary> /// XML Attribute text from the ennumeration value /// </summary> /// <param name="userAuthentication"></param> /// <returns></returns> public static string SiteUserAuthToAttributeText(SiteUserAuth userAuthentication) { switch (userAuthentication) { case SiteUserAuth.Default: return("ServerDefault"); case SiteUserAuth.SAML: return("SAML"); default: IwsDiagnostics.Assert(false, "810-1036: Unknown auth type for user "); throw new Exception("810-1036: Unknown auth type for user "); } }
/// <summary> /// Parse the attribute text /// </summary> /// <param name="parseText"></param> /// <returns></returns> public static MissingUserAction ParseMissingUserAction(string parseText) { if (parseText == AttributeValue_Report) { return(MissingUserAction.Report); } if (parseText == AttributeValue_Add) { return(MissingUserAction.Add); } IwsDiagnostics.Assert(false, "814-1015: Unkown value for ParseMissingUserAction: " + parseText); throw new Exception("814-1015: Unkown value for ParseMissingUserAction: " + parseText); }
/// <summary> /// Parse the attribute text /// </summary> /// <param name="parseText"></param> /// <returns></returns> public static UnexpectedGroupMemberAction ParseUnexpectedGroupMemberAction(string parseText) { if (parseText == AttributeValue_Report) { return(UnexpectedGroupMemberAction.Report); } if (parseText == AttributeValue_Delete) { return(UnexpectedGroupMemberAction.Delete); } IwsDiagnostics.Assert(false, "814-414: Unkown value: " + parseText); throw new Exception("814-414: Unkown value: " + parseText); }
/// <summary> /// Parse the attribute text /// </summary> /// <param name="parseText"></param> /// <returns></returns> public static UnexpectedUserAction ParseUnexpectedUserAction(string parseText) { if (parseText == AttributeValue_Report) { return(UnexpectedUserAction.Report); } if (parseText == AttributeValue_Unlicense) { return(UnexpectedUserAction.Unlicense); } IwsDiagnostics.Assert(false, "811-1105: Unkown value for ParseUnexpectedUserAction: " + parseText); throw new Exception("811-1105: Unkown value for ParseUnexpectedUserAction: " + parseText); }
/// <summary> /// Gives us a query string for the sort we want /// </summary> /// <returns></returns> private string SortDirectiveForContentQuery() { switch (_sort) { case Sort.NoSort: return(""); /* case Sort.SortByUpdatedDateNewestFirst: * return "sort=updatedAt:desc"; */ default: IwsDiagnostics.Assert(false, "Unknown workbook sort"); throw new Exception("Unknown workbook sort"); } }
/// <summary> /// Parse the attribute text /// </summary> /// <param name="parseText"></param> /// <returns></returns> public static ExistingUserAction ParseExistingUserAction(string parseText) { if (parseText == AttributeValue_Report) { return(ExistingUserAction.Report); } if (parseText == AttributeValue_Modify) { return(ExistingUserAction.Modify); } IwsDiagnostics.Assert(false, "814-1222: Unkown value for ParseExistingUserAction: " + parseText); throw new Exception("814-1222: Unkown value for ParseExistingUserAction: " + parseText); }
/// <summary> /// XML Serialization value /// </summary> /// <param name="action"></param> /// <returns></returns> internal static string XmlAttributeText(MissingGroupMemberAction action) { switch (action) { case MissingGroupMemberAction.Add: return(AttributeValue_Add); case MissingGroupMemberAction.Report: return(AttributeValue_Report); default: IwsDiagnostics.Assert(false, "814-412: Internal error, missing value"); throw new Exception("814-412: Internal error, missing value"); } }
/// <summary> /// Add a specific user into the Server Site's group /// </summary> /// <param name="userEmail"></param> /// <param name="thisProvisionGroup"></param> /// <param name="siteUsersList"></param> private void Execute_ProvisionGroups_SingleGroup_AddUser( TableauServerSignIn siteSignIn, string userEmail, SiteGroup siteGroup, WorkingListSiteUsers siteUsersList) { var siteUserToAddToGroup = siteUsersList.FindUserByName(userEmail); //Sanity test. If the user is not a member of the site, they cannot be added to a group if (siteUserToAddToGroup == null) { CSVRecord_ErrorUpdatingUser(userEmail, "", "", "User not on site. Cannot be added to group"); _statusLogs.AddError("User not on site. Cannot be added to group, " + userEmail); return; //FAILED } switch (_provisionInstructions.ActionForMissingGroupMembers) { case ProvisionUserInstructions.MissingGroupMemberAction.Add: //Call the server and add the user var addUserToGroup = new SendAddUserToGroup(siteSignIn, siteUserToAddToGroup.Id, siteGroup.Id); bool userGroupAddSuccess = addUserToGroup.ExecuteRequest(); if (userGroupAddSuccess) { //SUCCESS CSVRecord_GroupModified_WithUser(siteGroup.Name, "added member", siteUserToAddToGroup.Name, ""); _statusLogs.AddStatus("Group membership: Added " + siteUserToAddToGroup.Name + " to group " + siteGroup.Name); } else { CSVRecord_ErrorUpdatingUser(userEmail, "", "", "User could not be added to group " + siteGroup.Name); _statusLogs.AddError("Group membership error: Failed to add " + siteUserToAddToGroup.Name + " to group " + siteGroup.Name); } return; case ProvisionUserInstructions.MissingGroupMemberAction.Report: //We are instructed to NOT REALLY add the user, jsut report CSVRecord_GroupModified_WithUser(siteGroup.Name, "SIMULATED added member", siteUserToAddToGroup.Name, ""); return; default: IwsDiagnostics.Assert(false, "814-433: Unknown action"); throw new Exception("814-433: Unknown action"); } }
/// <summary> /// Parse the sign in mode /// </summary> /// <param name="xNodeTableauSite"></param> /// <returns></returns> private static TableauServerSignIn.SignInMode ParseSignInModeAttribute(XmlNode xNodeTableauSite) { string signInMode = xNodeTableauSite.Attributes["signInMode"].Value; switch (signInMode) { case SignInMode_NamePassword: return(TableauServerSignIn.SignInMode.UserNameAndPassword); case SignInMode_PersonalAccessToken: return(TableauServerSignIn.SignInMode.AuthToken); default: IwsDiagnostics.Assert(false, "819-1135: Unkown sign in mode, " + signInMode); throw new Exception("819-1135: Unkown sign in mode, " + signInMode); } }
/// <summary> /// Adds a user to the list, if an existing user does not already exist /// </summary> /// <param name="userToAdd"></param> public void AddUser(SiteUser userToAdd) { if (userToAdd == null) { IwsDiagnostics.Assert(false, "920-740: Null user being added to list"); throw new ArgumentException("920-740: Null user being added to list"); } var matchingExistingUser = FindUserByName(userToAdd.Name); if (matchingExistingUser != null) { IwsDiagnostics.Assert(false, "920-731: User already exists, " + userToAdd.Name); throw new Exception("920-731: User already exists, " + userToAdd.Name); } _usersList.Add(userToAdd); }
/// <summary> /// Update the unexpected user based on the specified behavior /// </summary> /// <param name="unexpectedUser"></param> /// <param name="siteSignIn"></param> /// <param name="behavior"></param> private void Execute_UpdateUnexpectedUsersProvisioning_SingleUser_WithBehavior( SiteUser unexpectedUser, TableauServerSignIn siteSignIn, ProvisionUserInstructions.UnexpectedUserAction behavior, WorkingListSiteUsers workingList_allKnownUsers) { switch (behavior) { case ProvisionUserInstructions.UnexpectedUserAction.Report: _statusLogs.AddStatus("No action: Keep unexpected user unaltered. User: "******"SIMULATED existing/removed", unexpectedUser.SiteRole + "->" + "Unlicensed"); return; } return; case ProvisionUserInstructions.UnexpectedUserAction.Unlicense: Execute_UpdateUnexpectedUsersProvisioning_SingleUser_WithBehavior_Unlicense( unexpectedUser, siteSignIn, workingList_allKnownUsers); return; case ProvisionUserInstructions.UnexpectedUserAction.Delete: Execute_UpdateUnexpectedUsersProvisioning_SingleUser_WithBehavior_Delete( unexpectedUser, siteSignIn, workingList_allKnownUsers); return; default: IwsDiagnostics.Assert(false, "811-1130: Internal error. Unknown provisioning behavior for user " + unexpectedUser.ToString()); _statusLogs.AddError("811-1130: Internal error. Unknown provisioning behavior for user " + unexpectedUser.ToString()); return; } }
/// <summary> /// Returns an double value /// </summary> /// <param name="settingName"></param> /// <param name="defaultValue"></param> /// <returns></returns> private static double GetAppSettingDouble(string settingName, int defaultValue) { if (string.IsNullOrWhiteSpace(settingName)) { IwsDiagnostics.Assert(false, "925-902, missing setting key"); throw new ArgumentException("925-902, missing setting key"); } string value = ConfigurationManager.AppSettings[settingName]; if (string.IsNullOrEmpty(value)) { return(defaultValue); } return(System.Convert.ToDouble(value)); }
/// <summary> /// Safe way to get a setting with a default value /// </summary> /// <param name="settingName"></param> /// <param name="defaultValue"></param> private static string GetAppSettingString(string settingName, string defaultValue = "") { if (string.IsNullOrWhiteSpace(settingName)) { IwsDiagnostics.Assert(false, "151210-0601, missing setting key"); throw new ArgumentException("151210-0601, missing setting key"); } string value = ConfigurationManager.AppSettings[settingName]; if (string.IsNullOrEmpty(value)) { return(defaultValue); } return(value); }