/// <summary> /// Creates a collection of SiteTag objects from XML returned by the Tableau server /// </summary> /// <param name="tagsNode"></param> public SiteTagsSet(XmlNode tagsNode) { if (tagsNode.Name.ToLower() != "tags") { AppDiagnostics.Assert(false, "Not tags"); throw new Exception("Unexpected content - not tags"); } //Namespace for XPath queries var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); //Build a set of tags var tags = new List <SiteTag>(); //Get the project tags var tagsSet = tagsNode.SelectNodes("iwsOnline:tag", nsManager); if (tagsSet != null) { foreach (var tagNode in tagsSet) { var newTag = new SiteTag((XmlNode)tagNode); tags.Add(newTag); } } _tags = tags.AsReadOnly(); }
/// <summary> /// Constructor /// </summary> /// <param name="scheduleNode"></param> public SiteSchedule(XmlNode scheduleNode) { var sbDevNotes = new StringBuilder(); if (scheduleNode.Name.ToLower() != "schedule") { AppDiagnostics.Assert(false, "Not a schedule"); throw new Exception("Unexpected content - not schedule"); } this.Id = scheduleNode.Attributes["id"].Value; this.ScheduleName = scheduleNode.Attributes["name"].Value; this.ScheduleState = scheduleNode.Attributes["state"].Value; this.ScheduleType = scheduleNode.Attributes["type"].Value; this.ScheduleFrequency = scheduleNode.Attributes["frequency"].Value; this.NextRunUTCText = scheduleNode.Attributes["nextRunAt"].Value; //This attribute is only present in hourly scheduled jobs const string attributeEndHourlyAt = "endScheduleAt"; if (scheduleNode.Attributes[attributeEndHourlyAt] != null) { this.EndScheduleIfHourlyUTC = scheduleNode.Attributes[attributeEndHourlyAt].Value; } this.PriorityText = scheduleNode.Attributes["priority"].Value; this.DeveloperNotes = sbDevNotes.ToString(); }
/// <summary> /// Constructor /// </summary> /// <param name="viewNode"></param> public SiteView(XmlNode viewNode) { var sbDevNotes = new StringBuilder(); if (viewNode.Name.ToLower() != "view") { AppDiagnostics.Assert(false, "Not a view"); throw new Exception("Unexpected content - not view"); } this.Id = viewNode.Attributes["id"].Value; this.Name = viewNode.Attributes["name"].Value; this.ContentUrl = viewNode.Attributes["contentUrl"].Value; //Namespace for XPath queries var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); //Get the user attributes var ownerNode = viewNode.SelectSingleNode("iwsOnline:owner", nsManager); this.OwnerId = ownerNode.Attributes["id"].Value; //Get information about the content being subscribed to (workbook or view) var workbookNode = viewNode.SelectSingleNode("iwsOnline:workbook", nsManager); this.WorkbookId = workbookNode.Attributes["id"].Value; //Get the schedule attibutes var usageNode = viewNode.SelectSingleNode("iwsOnline:usage", nsManager); this.TotalViewCount = System.Convert.ToInt64(usageNode.Attributes["totalViewCount"].Value); this.DeveloperNotes = sbDevNotes.ToString(); }
/// <summary> /// Look up any saved settings we have associated with a datasource on our local file systemm /// </summary> /// <param name="datasourceWithPath"></param> /// <returns></returns> internal static DatasourcePublishSettings GetSettingsForSavedDatasource(string datasourceWithPath) { //Sanity test: If the datasource is not there, then we probably have an incorrect path AppDiagnostics.Assert(File.Exists(datasourceWithPath), "Underlying datasource does not exist"); //Find the path to the settings file var pathToSettingsFile = PathForSettingsFile(datasourceWithPath); if (!File.Exists(pathToSettingsFile)) { return(new DatasourcePublishSettings(null)); } //=================================================================== //We've got a setings file, let's parse it! //=================================================================== var xmlDoc = new XmlDocument(); xmlDoc.Load(pathToSettingsFile); //Show sheets string ownerName = WorkbookPublishSettings.ParseXml_GetOwnerName(xmlDoc); //Return the Settings data return(new DatasourcePublishSettings(ownerName)); }
/// <summary> /// Get a page's worth of Users listings /// </summary> /// <param name="onlineUsers"></param> /// <param name="pageToRequest">Page # we are requesting (1 based)</param> /// <param name="totalNumberPages">Total # of pages of data that Server can return us</param> private void ExecuteRequest_ForPage(List <SiteUser> onlineUsers, int pageToRequest, out int totalNumberPages) { int pageSize = _onlineUrls.PageSize; var urlQuery = UrlForUsersListRequest(pageSize, pageToRequest); _onlineSession.StatusLog.AddStatus("Web request: " + urlQuery, -10); var xmlDoc = ResourceSafe_PerformWebRequest_GetXmlDocument(urlQuery, "get users list"); //Get all the user nodes var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var users = xmlDoc.SelectNodes("//iwsOnline:user", nsManager); //Get information for each of the data sources foreach (XmlNode itemXml in users) { try { var ds = new SiteUser(itemXml); onlineUsers.Add(ds); } catch { AppDiagnostics.Assert(false, "User parse error"); _onlineSession.StatusLog.AddError("Error parsing user: "******"//iwsOnline:pagination", nsManager), pageSize); }
/// <summary> /// Constructor /// </summary> /// <param name="groupNode"></param> public SiteGroup(XmlNode groupNode, IEnumerable <SiteUser> usersToPlaceInGroup) { //If we were passed in a set of users, store them var usersList = new List <SiteUser>(); if (usersToPlaceInGroup != null) { usersList.AddRange(usersToPlaceInGroup); } _usersInGroup = usersList; if (groupNode.Name.ToLower() != "group") { AppDiagnostics.Assert(false, "Not a group"); throw new Exception("Unexpected content - not group"); } this.Id = groupNode.Attributes["id"].Value; this.Name = groupNode.Attributes["name"].Value; //=================================================================================== //See if there is a GRANT LICENSE ON SIGN IN mode here //=================================================================================== //Get all the group nodes var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var xmlGroupImportNode = groupNode.SelectSingleNode(".//iwsOnline:import", nsManager); if (xmlGroupImportNode != null) { this.SiteMinimumRoleOrNull = XmlHelper.GetAttributeIfExists(xmlGroupImportNode, "siteRole", null); this.GrantLicenseMode = XmlHelper.GetAttributeIfExists(xmlGroupImportNode, "grantLicenseMode", null); } }
/// <summary> /// Look up any saved settings we have associated with a workbook on our local file systemm /// </summary> /// <param name="workbookWithPath"></param> /// <returns></returns> internal static WorkbookPublishSettings GetSettingsForSavedWorkbook(string workbookWithPath) { //Sanity test: If the workbook is not there, then we probably have an incorrect path AppDiagnostics.Assert(File.Exists(workbookWithPath), "Underlying workbook does not exist"); //Find the path to the settings file var pathToSettingsFile = PathForSettingsFile(workbookWithPath); if (!File.Exists(pathToSettingsFile)) { return(GenerateDefaultSettings()); } //=================================================================== //We've got a setings file, let's parse it! //=================================================================== var xmlDoc = new XmlDocument(); xmlDoc.Load(pathToSettingsFile); //Show sheets bool showSheetsInTabs = ParseXml_GetShowSheetsAsTabs(xmlDoc); string ownerName = ParseXml_GetOwnerName(xmlDoc); //Return the Settings data return(new WorkbookPublishSettings(showSheetsInTabs, ownerName)); }
private void _ExecuteRequest_ForPage(List <SiteView> onlineViews, int pageToRequest, out int totalNumberPages) { var pageSize = _onlineUrls.PageSize; var urlQuery = _onlineUrls.Url_ViewsListForSite(OnlineSession, pageSize, 1); var webRequest = CreateLoggedInWebRequest(urlQuery); webRequest.Method = "GET"; OnlineSession.StatusLog.AddStatus($"Web request: {urlQuery}", -10); var response = GetWebResponseLogErrors(webRequest, "get views list"); var xmlDoc = GetWebResponseAsXml(response); var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var workbooks = xmlDoc.SelectNodes("//iwsOnline:view", nsManager); _views = new List <SiteView>(); foreach (XmlNode itemXml in workbooks) { try { var ds = new SiteView(itemXml); _views.Add(ds); } catch { AppDiagnostics.Assert(false, "View parse error"); OnlineSession.StatusLog.AddError("Error parsing view: " + itemXml.InnerXml); } } totalNumberPages = DownloadPaginationHelper.GetNumberOfPagesFromPagination( xmlDoc.SelectSingleNode("//iwsOnline:pagination", nsManager), pageSize); }
/// <summary> /// Creates an instance of a SiteProject from XML returned by the Tableau server /// </summary> /// <param name="projectNode"></param> public SiteProject(XmlNode projectNode) { var sbDevNotes = new StringBuilder(); if (projectNode.Name.ToLower() != "project") { AppDiagnostics.Assert(false, "Not a project"); throw new Exception("Unexpected content - not project"); } if (projectNode.Attributes != null && projectNode.Attributes["contentPermission"] != null) { ContentPermission = projectNode.Attributes?["contentPermission"].Value; } if (projectNode.Attributes != null && projectNode.Attributes["description"] != null) { Description = projectNode.Attributes?["description"].Value; } if (projectNode.Attributes != null && projectNode.Attributes["parentProjectId"] != null) { ParentProjectId = projectNode.Attributes?["parentProjectId"].Value; } Id = projectNode.Attributes?["id"].Value; Name = projectNode.Attributes?["name"].Value; CreatedAt = projectNode.Attributes?["createdAt"].Value; UpdatedAt = projectNode.Attributes?["updatedAt"].Value; }
/// <summary> /// Create a SiteWorkbook from XML returned by the Tableau server /// </summary> /// <param name="workbookNode">XML node representing a Workbook</param> public SiteWorkbook(XmlNode workbookNode) : base(workbookNode) { if (workbookNode.Name.ToLower() != "workbook") { AppDiagnostics.Assert(false, "Not a workbook"); throw new Exception("Unexpected content - not workbook"); } if (workbookNode.Attributes != null && workbookNode.Attributes["description"] != null) { Description = workbookNode.Attributes?["description"].Value; } //Note: [2015-10-28] Datasources presently don't return this information, so we need to make this workbook specific ContentUrl = workbookNode.Attributes?["contentUrl"].Value; if (workbookNode.Attributes?["webpageUrl"] != null) { WebpageUrl = workbookNode.Attributes?["webpageUrl"].Value; } CreatedAt = workbookNode.Attributes?["createdAt"].Value; UpdatedAt = workbookNode.Attributes?["updatedAt"].Value; Size = workbookNode.Attributes?["size"].Value; //Do we have tabs? ShowTabs = XmlHelper.SafeParseXmlAttribute_Bool(workbookNode, "showTabs", false); }
/// <summary> /// Execute request for Workbook connections. /// </summary> public void ExecuteRequest() { var wbConnections = new List <SiteConnection>(); //Create a web request, in including the users logged-in auth information in the request headers var urlQuery = _onlineUrls.Url_WorkbookConnectionsList(OnlineSession, _workbookId); var webRequest = CreateLoggedInWebRequest(urlQuery); webRequest.Method = "GET"; OnlineSession.StatusLog.AddStatus("Web request: " + urlQuery, -10); var response = GetWebResponseLogErrors(webRequest, "get workbook's connections list"); var xmlDoc = GetWebResponseAsXml(response); //Get all the workbook nodes var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var connections = xmlDoc.SelectNodes("//iwsOnline:connection", nsManager); //Get information for each of the data sources foreach (XmlNode itemXml in connections) { try { var connection = new SiteConnection(itemXml); wbConnections.Add(connection); } catch { AppDiagnostics.Assert(false, "Workbook connections parse error"); OnlineSession.StatusLog.AddError("Error parsing workbook: " + itemXml.InnerXml); } } //end: foreach _connections = wbConnections; }
/// <summary> /// Constructor /// </summary> /// <param name="projectNode"></param> public SiteProject(XmlNode projectNode) { var sbDevNotes = new StringBuilder(); if (projectNode.Name.ToLower() != "project") { AppDiagnostics.Assert(false, "Not a project"); throw new Exception("Unexpected content - not project"); } this.Id = projectNode.Attributes["id"].Value; this.Name = projectNode.Attributes["name"].Value; var descriptionNode = projectNode.Attributes["description"]; if (descriptionNode != null) { this.Description = descriptionNode.Value; } else { this.Description = ""; sbDevNotes.AppendLine("Project is missing description attribute"); } this.DeveloperNotes = sbDevNotes.ToString(); }
/// <summary> /// /// </summary> /// <param name="serverName"></param> public void ExecuteRequest() { var dsConnections = new List <SiteConnection>(); //Create a web request, in including the users logged-in auth information in the request headers var urlQuery = _onlineUrls.Url_DatasourceConnectionsList(_onlineSession, _datasourceId); _onlineSession.StatusLog.AddStatus("Web request: " + urlQuery, -10); var xmlDoc = ResourceSafe_PerformWebRequest_GetXmlDocument(urlQuery, "get datasources's connections list"); //Get all the workbook nodes var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var connections = xmlDoc.SelectNodes("//iwsOnline:connection", nsManager); //Get information for each of the data sources foreach (XmlNode itemXml in connections) { try { var connection = new SiteConnection(itemXml); dsConnections.Add(connection); } catch { AppDiagnostics.Assert(false, "Workbook connections parse error"); _onlineSession.StatusLog.AddError("Error parsing workbook: " + itemXml.InnerXml); } } //end: foreach _connections = dsConnections; }
/// <summary> /// Constructor /// </summary> /// <param name="userNode">XML for user</param> /// <param name="userIdFixed">NULL if ID is expected in the XML. If non-NULL we will use the handed in user-id</param> private SiteUser(XmlNode userNode, string userIdFixed, SiteUserAuth?siteUserAuthFixed) { if (userNode.Name.ToLower() != "user") { AppDiagnostics.Assert(false, "Not a user"); throw new Exception("Unexpected content - not user"); } //If we have not been handed a user-id, then it must be in the XML if (string.IsNullOrEmpty(userIdFixed)) { this.Id = userNode.Attributes["id"].Value; } else { this.Id = userIdFixed; } this.Name = userNode.Attributes["name"].Value; this.SiteRole = userNode.Attributes["siteRole"].Value; this.LastLogin = XmlHelper.GetAttributeDateTimeIfExists(userNode, "lastLogin"); this.LastLoginAsText = XmlHelper.GetAttributeIfExists(userNode, "lastLogin", null); //Not all of the REST APIs return full name this.FullName = XmlHelper.GetAttributeIfExists(userNode, "fullName", ""); this.SiteRoleParsed = ParseUserRole(this.SiteRole); AppDiagnostics.Assert(this.SiteRoleParsed != SiteUserRole.Unknown, "Unknown user role: " + this.SiteRole); //If we were not passed in an explicit user authentication, then it needs to be in the XML if (siteUserAuthFixed == null) { this.SiteAuthentication = userNode.Attributes["authSetting"].Value; this.SiteAuthenticationParsed = ParseUserAuthentication(this.SiteAuthentication); AppDiagnostics.Assert(this.SiteAuthenticationParsed != SiteUserAuth.Unknown, "Unknown user auth: " + this.SiteAuthenticationParsed); } else { //Use the explicitly passed in value this.SiteAuthenticationParsed = siteUserAuthFixed.Value; this.SiteAuthentication = UserAuthenticationToString(this.SiteAuthenticationParsed); } this.IsSiteAdmin = ParseIsSiteAdmin(this.SiteRole); //============================================================================= //[2019-10-30] Currently Query User APIs do not return the user's email. //If the User Name is the email (as it is in Tableau Online) then grab that //============================================================================= string candidateEmail = this.Name; if (RegExHelper.IsEmail(candidateEmail)) { this.Email = candidateEmail; } }
/// <summary> /// Constructor /// </summary> /// <param name="flowNode"></param> public SiteFlow(XmlNode flowNode) : base(flowNode) { if (flowNode.Name.ToLower() != "flow") { AppDiagnostics.Assert(false, "Not a flow"); throw new Exception("Unexpected content - not flow"); } //Get the underlying data source type this.Description = flowNode.Attributes["description"].Value; }
/// <summary> /// Create an instance of a Site Tag from XML returned by the Tableau server /// </summary> /// <param name="tagNode"></param> public SiteTag(XmlNode tagNode) { if (tagNode.Name.ToLower() != "tag") { AppDiagnostics.Assert(false, "Not a tag"); throw new Exception("Unexpected content - not tag"); } Label = tagNode.Attributes?["label"].Value; }
/// <summary> /// /// </summary> /// <param name="str"></param> /// <returns></returns> private static bool ValidateTemplateReplaceComplete(string str) { if (str.Contains("{{iws")) { AppDiagnostics.Assert(false, "Template has incomplete parts that need to be replaced"); return(false); } return(true); }
/// <summary> /// Constructor /// </summary> /// <param name="datasourceNode"></param> public SiteDatasource(XmlNode datasourceNode) : base(datasourceNode) { if (datasourceNode.Name.ToLower() != "datasource") { AppDiagnostics.Assert(false, "Not a datasource"); throw new Exception("Unexpected content - not datasource"); } //Get the underlying data source type this.Type = datasourceNode.Attributes["type"].Value; }
/// <summary> /// Constructor /// </summary> /// <param name="userNode"></param> public SiteUser(XmlNode userNode) { if (userNode.Name.ToLower() != "user") { AppDiagnostics.Assert(false, "Not a user"); throw new Exception("Unexpected content - not user"); } this.Id = userNode.Attributes["id"].Value; this.Name = userNode.Attributes["name"].Value; this.SiteRole = userNode.Attributes["siteRole"].Value; }
public const int UploadFileChunkSize = 8000000; //8MB /// <summary> /// Constructor /// </summary> /// <param name="serverNameWithProtocol"></param> /// <param name="siteUrlSegment"></param> public TableauServerUrls(string protocol, string serverName, string siteUrlSegment, int pageSize, ServerVersion serverVersion) { //Cannonicalize the protocol protocol = protocol.ToLower(); this.ServerProtocol = protocol; this.PageSize = pageSize; string serverNameWithProtocol = protocol + serverName; this._serverVersion = serverVersion; this.SiteUrlSegement = siteUrlSegment; this.ServerName = serverName; this.ServerUrlWithProtocol = serverNameWithProtocol; this.UrlLogin = serverNameWithProtocol + "/api/2.3/auth/signin"; this.UrlLogout = serverNameWithProtocol + "/api/2.3/auth/signout"; this._urlListWorkbooksForUserTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/users/{{iwsUserId}}/workbooks?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListWorkbookConnectionsTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}/connections"; this._urlListDatasourcesTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/datasources?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListProjectsTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/projects?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListSubscriptionsTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/subscriptions?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListSchedulesTemplate = serverNameWithProtocol + "/api/2.3/schedules?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListTasksInScheduleTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/schedules/{{iwsScheduleId}}/extracts?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListViewsTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/views?includeUsageStatistics=true&pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListGroupsTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/groups?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListUsersTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/users?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlListUsersInGroupTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/groups/{{iwsGroupId}}/users?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; this._urlDownloadDatasourceTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/datasources/{{iwsRepositoryId}}/content"; this._urlDownloadWorkbookTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/workbooks/{{iwsRepositoryId}}/content"; this._urlSiteInfoTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}"; this._urlInitiateUploadTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/fileUploads"; this._urlAppendUploadChunkTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/fileUploads/{{iwsUploadSession}}"; this._urlFinalizeUploadDatasourceTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/datasources?uploadSessionId={{iwsUploadSession}}&datasourceType={{iwsDatasourceType}}&overwrite=true"; this._urlFinalizeUploadWorkbookTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/workbooks?uploadSessionId={{iwsUploadSession}}&workbookType={{iwsWorkbookType}}&overwrite=true"; this._urlCreateProjectTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/projects"; this._urlDeleteWorkbookTagTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}/tags/{{iwsTagText}}"; this._urlDeleteDatasourceTagTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/datasources/{{iwsDatasourceId}}/tags/{{iwsTagText}}"; this._urlUpdateWorkbookTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}"; this._urlUpdateDatasourceTemplate = serverNameWithProtocol + "/api/2.3/sites/{{iwsSiteId}}/datasources/{{iwsDatasourceId}}"; //Any server version specific things we want to do? switch (serverVersion) { case ServerVersion.server8: throw new Exception("This app does not support v8 Server"); case ServerVersion.server9: break; default: AppDiagnostics.Assert(false, "Unknown server version"); throw new Exception("Unknown server version"); } }
/// <summary> /// Generates the path/filename of the Settings file that corresponds to the workbook path /// </summary> /// <param name="workbookPath"></param> /// <returns></returns> internal static string PathForSettingsFile(string workbookPath) { //Sanity test if (string.IsNullOrWhiteSpace(workbookPath)) { AppDiagnostics.Assert(false, "missing path"); throw new ArgumentNullException("missing path"); } //Tag an extra extension to the file return(workbookPath + WorkbookSettingsSuffix); }
private SiteUser UpdateUser(string userId, string newRole, SiteUserAuth newAuthentication) { AppDiagnostics.Assert(!string.IsNullOrWhiteSpace(userId), "missing user id"); AppDiagnostics.Assert(!string.IsNullOrWhiteSpace(newRole), "missing role"); string newAuthenticationText = SendCreateUser.SiteUserAuthToAttributeText(newAuthentication); //ref: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#update_user var sb = new StringBuilder(); var xmlWriter = XmlWriter.Create(sb, XmlHelper.XmlSettingsForWebRequests); xmlWriter.WriteStartElement("tsRequest"); xmlWriter.WriteStartElement("user"); xmlWriter.WriteAttributeString("siteRole", newRole); xmlWriter.WriteAttributeString("authSetting", newAuthenticationText); xmlWriter.WriteEndElement(); //</user> xmlWriter.WriteEndElement(); // </tsRequest> xmlWriter.Close(); var xmlText = sb.ToString(); //Get the XML text out //Create a web request var urlUpdateUser = _onlineUrls.Url_UpdateSiteUser(_onlineSession, userId); var webRequest = this.CreateLoggedInWebRequest(urlUpdateUser, "PUT"); TableauServerRequestBase.SendPutContents(webRequest, xmlText); //Get the response var response = GetWebReponseLogErrors(webRequest, "update yser (change auth or role)"); using (response) { var xmlDoc = GetWebResponseAsXml(response); //Get all the user nodes var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var xNodeUser = xmlDoc.SelectSingleNode("//iwsOnline:user", nsManager); try { return(SiteUser.FromUserXMLWithoutUserId(xNodeUser, userId)); } catch (Exception parseXml) { StatusLog.AddError("Update user, error parsing XML response " + parseXml.Message + "\r\n" + xNodeUser.InnerXml); return(null); } } }
/// <summary> /// Constructor /// </summary> /// <param name="workbookNode"></param> public SiteWorkbook(XmlNode workbookNode) : base(workbookNode) { if (workbookNode.Name.ToLower() != "workbook") { AppDiagnostics.Assert(false, "Not a workbook"); throw new Exception("Unexpected content - not workbook"); } //Note: [2015-10-28] Datasources presently don't return this information, so we need to make this workbook specific this.ContentUrl = workbookNode.Attributes["contentUrl"].Value; //Do we have tabs? this.ShowTabs = XmlHelper.SafeParseXmlAttribute_Bool(workbookNode, "showTabs", false); }
/// <summary> /// Open a file in the Windows shell (e.g. open a textfile or csv file) /// </summary> /// <param name="path"></param> /// <returns></returns> private bool AttemptToShellFile(string path) { try { System.Diagnostics.Process.Start(path); } catch (Exception ex) { AppDiagnostics.Assert(false, "Failure to shell file: " + ex.Message); return(false); } return(true); //Success }
public SiteinfoSite(XmlNode content) { if (content.Name.ToLower() != "site") { AppDiagnostics.Assert(false, "Not a site"); throw new Exception("Unexpected content - not site"); } this.Name = content.Attributes["name"].Value; this.Id = content.Attributes["id"].Value; this.ContentUrl = content.Attributes["contentUrl"].Value; this.AdminMode = content.Attributes["adminMode"].Value; this.State = content.Attributes["state"].Value; }
public const int UploadFileChunkSize = 8000000; //8MB /// <summary> /// Constructor /// </summary> /// <param name="serverName">Server IP, hostname or FQDN</param> /// <param name="siteName">Tableau Site Name</param> /// <param name="protocol">HTTP protocol</param> /// <param name="pageSize">Page size, defaults to 1000</param> /// <param name="serverVersion">Tableau Server version</param> public TableauServerUrls(ServerProtocol protocol, string serverName, string siteName, int pageSize = 1000, ServerVersion serverVersion = ServerVersion.Server9) { PageSize = 1000; ServerProtocol = protocol; PageSize = pageSize; var serverNameWithProtocol = (protocol == ServerProtocol.Http ? "http://" : "https://") + serverName; ServerVersion = serverVersion; SiteUrlSegement = siteName; ServerName = serverName; ServerUrlWithProtocol = serverNameWithProtocol; UrlLogin = serverNameWithProtocol + "/api/3.3/auth/signin"; _urlListWorkbooksForUserTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/users/{{iwsUserId}}/workbooks?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; _urlViewsListForSiteTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/views?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; _urlViewThumbnailTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}/views/{{iwsViewId}}/previewImage"; _urlViewDataTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/views/{{iwsViewId}}/data"; _urlListViewsForWorkbookTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}/views"; _urlListWorkbookConnectionsTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}/connections"; _urlWorkbookTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}"; _urlListDatasourcesTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/datasources?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; _urlListProjectsTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/projects?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; _urlListGroupsTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/groups?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; _urlListUsersTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/users?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; _urlListUsersInGroupTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/groups/{{iwsGroupId}}/users?pageSize={{iwsPageSize}}&pageNumber={{iwsPageNumber}}"; _urlDownloadDatasourceTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/datasources/{{iwsRepositoryId}}/content"; _urlDatasourceConnectionsTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/datasources/{{iwsRepositoryId}}/connections"; _urlDownloadWorkbookTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/workbooks/{{iwsRepositoryId}}/content"; _urlSiteInfoTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}"; _urlInitiateUploadTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/fileUploads"; _urlAppendUploadChunkTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/fileUploads/{{iwsUploadSession}}"; _urlFinalizeUploadDatasourceTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/datasources?uploadSessionId={{iwsUploadSession}}&datasourceType={{iwsDatasourceType}}&overwrite=true"; _urlFinalizeUploadWorkbookTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/workbooks?uploadSessionId={{iwsUploadSession}}&workbookType={{iwsWorkbookType}}&overwrite=true"; _urlCreateProjectTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/projects"; _urlDeleteWorkbookTagTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/workbooks/{{iwsWorkbookId}}/tags/{{iwsTagText}}"; _urlDeleteDatasourceTagTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/datasources/{{iwsDatasourceId}}/tags/{{iwsTagText}}"; _urlUpdateUserTemplate = serverNameWithProtocol + "/api/3.3/sites/{{iwsSiteId}}/users/{{iwsUserId}}"; //Any server version specific things we want to do? switch (serverVersion) { case ServerVersion.Server9: break; default: AppDiagnostics.Assert(false, "Unknown server version"); throw new Exception("Unknown server version"); } }
private SiteFlow ChangeContentOwner(string flowId, string newOwnerId) { AppDiagnostics.Assert(!string.IsNullOrWhiteSpace(flowId), "missing flow id"); AppDiagnostics.Assert(!string.IsNullOrWhiteSpace(newOwnerId), "missing owner id"); //ref: https://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm#REST/rest_api_ref.htm#Update_Flow%3FTocPath%3DAPI%2520Reference%7C_____76 var sb = new StringBuilder(); var xmlWriter = XmlWriter.Create(sb, XmlHelper.XmlSettingsForWebRequests); xmlWriter.WriteStartElement("tsRequest"); xmlWriter.WriteStartElement("flow"); xmlWriter.WriteStartElement("owner"); xmlWriter.WriteAttributeString("id", newOwnerId); xmlWriter.WriteEndElement(); //</owner> xmlWriter.WriteEndElement(); //</flow> xmlWriter.WriteEndElement(); // </tsRequest> xmlWriter.Close(); var xmlText = sb.ToString(); //Get the XML text out //Create a web request var urlUpdateFlow = _onlineUrls.Url_UpdateFlow(_onlineSession, flowId); var webRequest = this.CreateLoggedInWebRequest(urlUpdateFlow, "PUT"); TableauServerRequestBase.SendPutContents(webRequest, xmlText); //Get the response var response = GetWebReponseLogErrors(webRequest, "update flow (change owner)"); using (response) { var xmlDoc = GetWebResponseAsXml(response); //Get all the flow nodes var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var xNodeDs = xmlDoc.SelectSingleNode("//iwsOnline:flow", nsManager); try { return(new SiteFlow(xNodeDs)); } catch (Exception parseXml) { StatusLog.AddError("Change flow owner, error parsing XML response " + parseXml.Message + "\r\n" + xNodeDs.InnerXml); return(null); } } }
/// <summary> /// Get an upload sessiosn Id /// </summary> /// <returns></returns> private string RequestUploadSessionId() { var urlInitiateFileUpload = _onlineUrls.Url_InitiateFileUpload(_onlineSession); var webRequest = this.CreateLoggedInWebRequest(urlInitiateFileUpload, "POST"); //NOTE: This command requires a POST not a GET var xmlDoc = GetWebReponseLogErrors_AsXmlDoc(webRequest, "get datasources list"); //Get all the workbook nodes var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var uploadInfo = xmlDoc.SelectSingleNode("//iwsOnline:fileUpload", nsManager); var sessionId = uploadInfo.Attributes["uploadSessionId"].Value; AppDiagnostics.Assert(!string.IsNullOrWhiteSpace(sessionId), "Empty upload session id?"); return(sessionId); }
/// <summary> /// Create a SiteView from XML returned by the Tableau server /// </summary> /// <param name="xmlNode"></param> public SiteView(XmlNode xmlNode) : base(xmlNode) { if (xmlNode.Name.ToLower() != "view") { AppDiagnostics.Assert(false, "Not a view"); throw new Exception("Unexpected content - not a view"); } this.ContentUrl = xmlNode.Attributes?["contentUrl"].Value; var workbookNode = xmlNode.SelectSingleNode("iwsOnline:workbook", NamespaceManager); if (workbookNode != null) { this.WorkbookId = xmlNode.Attributes?["id"].Value; } }
/// <summary> /// Looks /// </summary> /// <param name="ownerId">GUID of content owner</param> /// <param name="userLookups">set we are looking the owner up in</param> /// <returns></returns> internal static string helper_LookUpOwnerId(string ownerId, KeyedLookup <SiteUser> userLookups) { //Sanity test AppDiagnostics.Assert(!string.IsNullOrWhiteSpace(ownerId), "blank owner id to look up?"); string contentOwnerName; var contentOwner = userLookups.FindItem(ownerId); //This should only ever happen if there is a race condition between getting the list of users, and downloading the content, where a user did not exist when we asked for the list of users //Should be very rare if (contentOwner == null) { return(UnknownOwnerName); } return(contentOwnerName = contentOwner.Name); }