Ejemplo n.º 1
0
    /// <summary>
    /// Sanity testing on whether the file being uploaded is worth uploading
    /// </summary>
    /// <param name="localFilePath"></param>
    /// <returns></returns>
    bool IsValidUploadFile(string localFilePath)
    {
        //If the file is a custom settings file for the workbook, then ignore it
        if (DatasourcePublishSettings.IsSettingsFile(localFilePath))
        {
            return(false); //Nothing to do, it's just a settings file
        }

        //Ignore temp files, since we know we don't want to upload them
        var fileExtension = Path.GetExtension(localFilePath).ToLower();

        if ((fileExtension == ".tmp") || (fileExtension == ".temp"))
        {
            StatusLog.AddStatus("Ignoring temp file, " + localFilePath, -10);
            return(false);
        }

        //These are the only kinds of data sources we know about...
        if ((fileExtension != ".tds") && (fileExtension != ".tdsx"))
        {
            StatusLog.AddError("File is not a data source: " + localFilePath);
            return(false);
        }

        return(true);
    }
Ejemplo n.º 2
0
        /// <summary>
        /// Attempts to upload a single file a Tableau Server, and then make it a published data source
        /// </summary>
        /// <param name="localFilePath"></param>
        /// <param name="projectId"></param>
        /// <param name="dbCredentials">If not NULL, then these are the DB credentials we want to associate with the content we are uploading</param>
        /// <returns></returns>
        private bool AttemptUploadSingleFile(
            string localFilePath,
            string projectId,
            CredentialManager.Credential dbCredentials,
            DatasourcePublishSettings publishSettings)
        {
            string uploadSessionId;

            try
            {
                var fileUploader = new UploadFile(Urls, Login, localFilePath, HttpClientFactory, UploadChunkSizeBytes, UploadChunkDelaySeconds);
                uploadSessionId = fileUploader.ExecuteRequest();
            }
            catch (Exception exFileUpload)
            {
                Login.Logger.Error("Unexpected error attempting to upload file " + localFilePath + ", " + exFileUpload.Message);
                throw exFileUpload;
            }

            SiteDatasource dataSource = null;

            Login.Logger.Information("File chunks upload successful. Next step, make it a published datasource");
            try
            {
                string fileName   = Path.GetFileNameWithoutExtension(localFilePath);
                string uploadType = RemoveFileExtensionDot(Path.GetExtension(localFilePath).ToLower());
                dataSource = FinalizePublish(
                    uploadSessionId,
                    FileIOHelper.Undo_GenerateWindowsSafeFilename(fileName), //[2016-05-06] If the name has escapted characters, unescape them
                    uploadType,
                    projectId,
                    dbCredentials);
                UploadeDatasources.Add(dataSource);
                Login.Logger.Information("Upload content details: " + dataSource.ToString());
                Login.Logger.Information("Success! Uploaded datasource " + Path.GetFileName(localFilePath));
            }
            catch (Exception exPublishFinalize)
            {
                Login.Logger.Error("Unexpected error finalizing publish of file " + localFilePath + ", " + exPublishFinalize.Message);
                throw exPublishFinalize;;
            }

            //See if we want to reassign ownership of the datasource
            if (AttemptOwnershipAssignment)
            {
                try
                {
                    AttemptOwnerReassignment(dataSource, publishSettings, SiteUsers);
                }
                catch (Exception exOwnershipAssignment)
                {
                    Login.Logger.Error("Unexpected error reassigning ownership of published datasource " + dataSource.Name + ", " + exOwnershipAssignment.Message);
                    LogManualAction_ReassignOwnership(dataSource.Name);
                    throw exOwnershipAssignment;
                }
            }

            return(true);     //Success
        }
Ejemplo n.º 3
0
    /// <summary>
    /// Assign ownership
    /// </summary>
    /// <param name="datasource"></param>
    /// <param name="publishSettings"></param>
    /// <param name="siteUsers"></param>
    /// <returns>TRUE: The server content has the correct owner now.  FALSE: We were unable to give the server content the correct owner</returns>
    private bool AttemptOwnerReassignment(SiteDatasource datasource, DatasourcePublishSettings publishSettings, IEnumerable <SiteUser> siteUsers)
    {
        this.StatusLog.AddStatusHeader("Attempting ownership assignement for Datasource " + datasource.Name + "/" + datasource.Id);

        //Something went wrong if we don't have a set of site users to do the look up
        if (siteUsers == null)
        {
            throw new ArgumentException("No set of site users provided for lookup");
        }

        //Look the local meta data to see what the desired name is
        var desiredOwnerName = publishSettings.OwnerName;

        if (string.IsNullOrEmpty(desiredOwnerName))
        {
            this.StatusLog.AddStatus("Skipping owner assignment. The local file system has no metadata with an owner information for " + datasource.Name);
            LogManualAction_ReassignOwnership(datasource.Name, "none specified", "No client ownership information was specified");
            return(true); //Since there is no ownership preference stated locally, then ownership we assigned during upload was fine.
        }

        //Look on the list of users in the target site/server, and try to find a match
        //
        //NOTE: We are doing a CASE INSENSITIVE name comparison. We assume that there are not 2 users with the same name on server w/differet cases
        //      Because if this, we want to be flexible and allow that our source/destination servers may have the user name specified with a differnt
        //      case.  -- This is less secure than a case-sensitive comparison, but is almost always what we want when porting content between servers
        var desiredServerUser = SiteUser.FindUserWithName(siteUsers, desiredOwnerName, StringComparison.InvariantCultureIgnoreCase);

        if (desiredServerUser == null)
        {
            this.StatusLog.AddError("The local file has a workbook/user mapping: " + datasource.Name + "/" + desiredOwnerName + ", but this user does not exist on the target site");
            LogManualAction_ReassignOwnership(datasource.Name, desiredOwnerName, "The target site does not contain a user name that matches the owner specified by the local metadata");
            return(false); //Not a run time error, but we have manual steps to perform
        }

        //If the server content is already correct, then there is nothing to do
        if (desiredServerUser.Id == datasource.OwnerId)
        {
            this.StatusLog.AddStatus("Workbook " + datasource.Name + "/" + datasource.Id + ", already has correct ownership. No update requried");
            return(true);
        }

        //Lets tell server to update the owner
        var            changeOwnership = new SendUpdateDatasourceOwner(_onlineUrls, _onlineSession, datasource.Id, desiredServerUser.Id);
        SiteDatasource updatedDatasource;

        try
        {
            this.StatusLog.AddStatus("Server request to change Datasource ownership, ds: " + datasource.Name + "/" + datasource.Id + ", user:"******"/" + desiredServerUser.Id);
            updatedDatasource = changeOwnership.ExecuteRequest();
        }
        catch (Exception exChangeOnwnerhsip)
        {
            throw exChangeOnwnerhsip; //Unexpected error, send it upward
        }

        //Sanity check the result we got back: Double check to make sure we have the expected owner.
        if (updatedDatasource.OwnerId != desiredServerUser.Id)
        {
            this.StatusLog.AddError("Unexpected server error! Updated workbook Owner Id does not match expected. ds: "
                                    + datasource.Name + "/" + datasource.Id + ", "
                                    + "expected user: "******", "
                                    + "actual user: " + updatedDatasource.OwnerId
                                    );
        }

        return(true);
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Uploads the contents of a directory to server
    /// </summary>
    /// <param name="rootContentPath"></param>
    /// <param name="currentContentPath"></param>
    /// <param name="recurseDirectories"></param>
    private void UploadDirectoryToServer(
        string rootContentPath,
        string currentContentPath,
        ProjectFindCreateHelper projectsList,
        bool recurseDirectories,
        out int countSuccess,
        out int countFailure)
    {
        countSuccess = 0;
        countFailure = 0;

        //Look up the project name based on directory name, and creating a project on demand
        string projectName;

        if (rootContentPath == currentContentPath) //If we are in the root upload directory, then assume any content goes to the Default project
        {
            projectName = "";                      //Default project
        }
        else
        {
            projectName = FileIOHelper.Undo_GenerateWindowsSafeFilename(Path.GetFileName(currentContentPath));
        }


        //Start off with no project ID -- we'll look it up as needed
        string projectIdForUploads = null;

        //-------------------------------------------------------------------------------------
        //Upload the files from local directory to server
        //-------------------------------------------------------------------------------------
        foreach (var thisFilePath in Directory.GetFiles(currentContentPath))
        {
            bool isValidUploadFile = IsValidUploadFile(thisFilePath);

            if (isValidUploadFile)
            {
                //If we don't yet have a project ID, then get one
                if (string.IsNullOrWhiteSpace(projectIdForUploads))
                {
                    projectIdForUploads = projectsList.GetProjectIdForUploads(projectName);
                }

                try
                {
                    //See if there are any credentials we want to publish with the content
                    var dbCredentialsIfAny = helper_DetermineContentCredential(
                        Path.GetFileName(thisFilePath),
                        projectName);

                    //See what content specific settings there may be for this workbook
                    var publishSettings = DatasourcePublishSettings.GetSettingsForSavedDatasource(thisFilePath);

                    //Do the file upload
                    bool wasFileUploaded = AttemptUploadSingleFile(thisFilePath, projectIdForUploads, dbCredentialsIfAny, publishSettings);
                    if (wasFileUploaded)
                    {
                        countSuccess++;
                    }
                }
                catch (Exception ex)
                {
                    countFailure++;
                    StatusLog.AddError("Error uploading datasource " + thisFilePath + ". " + ex.Message);
                    LogManualAction_UploadDataSource(thisFilePath);
                }
            }
        }

        //If we are running recursive , then look in the subdirectories too
        if (recurseDirectories)
        {
            int subDirSuccess;
            int subDirFailure;
            foreach (var subDirectory in Directory.GetDirectories(currentContentPath))
            {
                UploadDirectoryToServer(rootContentPath, subDirectory, projectsList, true, out subDirSuccess, out subDirFailure);
                countSuccess += subDirSuccess;
                countFailure += subDirFailure;
            }
        }
    }
Ejemplo n.º 5
0
    /// <summary>
    ///
    /// </summary>
    /// <param name="serverName"></param>
    public List <SiteDatasource> ExecuteRequest()
    {
        var statusLog         = _onlineSession.StatusLog;
        var downloadedContent = new List <SiteDatasource>();

        //Depending on the HTTP download file type we want different file extensions
        var typeMapper = new DownloadPayloadTypeHelper("tdsx", "tds");

        var datasources = _datasources;

        if (datasources == null)
        {
            statusLog.AddError("NULL datasources. Aborting download.");
            return(null);
        }

        //For each datasource, download it and save it to the local file system
        foreach (var dsInfo in datasources)
        {
            //Local path save the workbook
            string urlDownload = _onlineUrls.Url_DatasourceDownload(_onlineSession, dsInfo);
            statusLog.AddStatus("Starting Datasource download " + dsInfo.Name);
            try
            {
                //Generate the directory name we want to download into
                var pathToSaveTo = FileIOHelper.EnsureProjectBasedPath(
                    _localSavePath,
                    _downloadToProjectDirectories,
                    dsInfo,
                    this.StatusLog);

                var fileDownloaded       = this.DownloadFile(urlDownload, pathToSaveTo, dsInfo.Name, typeMapper);
                var fileDownloadedNoPath = System.IO.Path.GetFileName(fileDownloaded);
                statusLog.AddStatus("Finished Datasource download " + fileDownloadedNoPath);

                //Add to the list of our downloaded data sources
                if (!string.IsNullOrEmpty(fileDownloaded))
                {
                    downloadedContent.Add(dsInfo);

                    //Generate the metadata file that has additional server provided information about the workbook
                    if (_generateInfoFile)
                    {
                        DatasourcePublishSettings.CreateSettingsFile(dsInfo, fileDownloaded, _siteUserLookup);
                    }
                }
                else
                {
                    //We should never hit this code; just being defensive
                    statusLog.AddError("Download error, no local file path for downloaded content");
                }
            }
            catch (Exception ex)
            {
                statusLog.AddError("Error during Datasource download " + dsInfo.Name + "\r\n  " + urlDownload + "\r\n  " + ex.ToString());
            }
        } //foreach


        //Return the set of successfully downloaded content
        return(downloadedContent);
    }
Ejemplo n.º 6
0
    /// <summary>
    /// Attempts to upload a single file a Tableau Server, and then make it a published data source
    /// </summary>
    /// <param name="localFilePath"></param>
    /// <param name="projectId"></param>
    /// <param name="dbCredentials">If not NULL, then these are the DB credentials we want to associate with the content we are uploading</param>
    /// <returns></returns>
    private bool AttemptUploadSingleFile(
        string localFilePath, 
        string projectId,
        CredentialManager.Credential dbCredentials,
        DatasourcePublishSettings publishSettings)
    {
        string uploadSessionId;
        try
        {
            var fileUploader = new UploadFile(_onlineUrls, _onlineSession, localFilePath, _uploadChunkSizeBytes, _uploadChunkDelaySeconds);
            uploadSessionId = fileUploader.ExecuteRequest();
        }
        catch (Exception exFileUpload)
        {
            this.StatusLog.AddError("Unexpected error attempting to upload file " + localFilePath + ", " + exFileUpload.Message);
            throw exFileUpload;
        }

        SiteDatasource dataSource = null;
        this.StatusLog.AddStatus("File chunks upload successful. Next step, make it a published datasource", -10);
        try
        {
            string fileName = Path.GetFileNameWithoutExtension(localFilePath);
            string uploadType = RemoveFileExtensionDot(Path.GetExtension(localFilePath).ToLower());
            dataSource = FinalizePublish(
                uploadSessionId,
                FileIOHelper.Undo_GenerateWindowsSafeFilename(fileName), //[2016-05-06] If the name has escapted characters, unescape them
                uploadType,
                projectId,
                dbCredentials);
            StatusLog.AddStatus("Upload content details: " + dataSource.ToString(), -10);
            StatusLog.AddStatus("Success! Uploaded datasource " + Path.GetFileName(localFilePath));
        }
        catch (Exception exPublishFinalize)
        {
            this.StatusLog.AddError("Unexpected error finalizing publish of file " + localFilePath + ", " + exPublishFinalize.Message);
            throw exPublishFinalize; ;

        }

        //See if we want to reassign ownership of the datasource
        if (_attemptOwnershipAssignment)
        {
            try
            {
                AttemptOwnerReassignment(dataSource, publishSettings, _siteUsers);
            }
            catch (Exception exOwnershipAssignment)
            {
                this.StatusLog.AddError("Unexpected error reassigning ownership of published datasource " + dataSource.Name + ", " + exOwnershipAssignment.Message);
                LogManualAction_ReassignOwnership(dataSource.Name);
                throw exOwnershipAssignment;
            }
        }

        return true;     //Success
    }
Ejemplo n.º 7
0
    /// <summary>
    /// Assign ownership
    /// </summary>
    /// <param name="datasource"></param>
    /// <param name="publishSettings"></param>
    /// <param name="siteUsers"></param>
    /// <returns>TRUE: The server content has the correct owner now.  FALSE: We were unable to give the server content the correct owner</returns>
    private bool AttemptOwnerReassignment(SiteDatasource datasource, DatasourcePublishSettings publishSettings, IEnumerable<SiteUser> siteUsers)
    {
        this.StatusLog.AddStatusHeader("Attempting ownership assignement for Datasource " + datasource.Name + "/" + datasource.Id);

        //Something went wrong if we don't have a set of site users to do the look up
        if (siteUsers == null)
        {
            throw new ArgumentException("No set of site users provided for lookup");
        }

        //Look the local meta data to see what the desired name is
        var desiredOwnerName = publishSettings.OwnerName;
        if (string.IsNullOrEmpty(desiredOwnerName))
        {
            this.StatusLog.AddStatus("Skipping owner assignment. The local file system has no metadata with an owner information for " + datasource.Name);
            LogManualAction_ReassignOwnership(datasource.Name, "none specified", "No client ownership information was specified");
            return true; //Since there is no ownership preference stated locally, then ownership we assigned during upload was fine.
        }

        //Look on the list of users in the target site/server, and try to find a match
        //
        //NOTE: We are doing a CASE INSENSITIVE name comparison. We assume that there are not 2 users with the same name on server w/differet cases
        //      Because if this, we want to be flexible and allow that our source/destination servers may have the user name specified with a differnt
        //      case.  -- This is less secure than a case-sensitive comparison, but is almost always what we want when porting content between servers
        var desiredServerUser = SiteUser.FindUserWithName(siteUsers, desiredOwnerName, StringComparison.InvariantCultureIgnoreCase);

        if (desiredServerUser == null)
        {
            this.StatusLog.AddError("The local file has a workbook/user mapping: " + datasource.Name + "/" + desiredOwnerName + ", but this user does not exist on the target site");
            LogManualAction_ReassignOwnership(datasource.Name, desiredOwnerName, "The target site does not contain a user name that matches the owner specified by the local metadata");
            return false; //Not a run time error, but we have manual steps to perform
        }

        //If the server content is already correct, then there is nothing to do
        if (desiredServerUser.Id == datasource.OwnerId)
        {
            this.StatusLog.AddStatus("Workbook " + datasource.Name + "/" + datasource.Id + ", already has correct ownership. No update requried");
            return true;
        }

        //Lets tell server to update the owner
        var changeOwnership = new SendUpdateDatasourceOwner(_onlineUrls, _onlineSession, datasource.Id, desiredServerUser.Id);
        SiteDatasource updatedDatasource;
        try
        {
            this.StatusLog.AddStatus("Server request to change Datasource ownership, ds: " + datasource.Name + "/" + datasource.Id + ", user:"******"/" + desiredServerUser.Id);
            updatedDatasource = changeOwnership.ExecuteRequest();
        }
        catch (Exception exChangeOnwnerhsip)
        {
            throw exChangeOnwnerhsip; //Unexpected error, send it upward
        }

        //Sanity check the result we got back: Double check to make sure we have the expected owner.
        if (updatedDatasource.OwnerId != desiredServerUser.Id)
        {
            this.StatusLog.AddError("Unexpected server error! Updated workbook Owner Id does not match expected. ds: "
                + datasource.Name + "/" + datasource.Id + ", "
                + "expected user: "******", "
                + "actual user: " + updatedDatasource.OwnerId
                );
        }

        return true;
    }