Пример #1
0
        /// <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();
        }
Пример #2
0
    /// <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();
    }
Пример #3
0
    /// <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));
    }
Пример #5
0
    /// <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);
    }
Пример #6
0
    /// <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);
        }
    }
Пример #7
0
    /// <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);
        }
Пример #9
0
        /// <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;
        }
Пример #10
0
        /// <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;
        }
Пример #12
0
    /// <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();
    }
Пример #13
0
    /// <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;
    }
Пример #14
0
    /// <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;
        }
    }
Пример #15
0
 /// <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;
 }
Пример #16
0
        /// <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;
        }
Пример #17
0
    /// <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);
    }
Пример #18
0
 /// <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;
 }
Пример #19
0
    /// <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;
    }
Пример #20
0
    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");
        }
    }
Пример #21
0
    /// <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);
    }
Пример #22
0
    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);
            }
        }
    }
Пример #23
0
    /// <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);
    }
Пример #24
0
        /// <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
        }
Пример #25
0
    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");
            }
        }
Пример #27
0
    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);
            }
        }
    }
Пример #28
0
    /// <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);
    }
Пример #29
0
        /// <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;
            }
        }
Пример #30
0
    /// <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);
    }