### Example: Initialize and Start Deletion Job Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md Demonstrates how to create a DeletePasswordJob, set the key for the secret to be deleted, and start the job. ```cpp auto deleteJob = new QKeychain::DeletePasswordJob("com.example.myapp"); deleteJob->setKey("old_api_token"); deleteJob->start(); ``` -------------------------------- ### Start a Read Password Job Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md This example demonstrates how to create, configure, and start a job to read a password from the keychain. Ensure you connect to the finished signal to handle the job's completion. ```cpp auto job = new QKeychain::ReadPasswordJob("myservice"); job->setKey("username"); connect(job, &QKeychain::Job::finished, this, &MyClass::onJobFinished); job->start(); // Enqueue the job ``` -------------------------------- ### Installation Rules Source: https://github.com/frankosterfeld/qtkeychain/blob/main/TestAppExample/CMakeLists.txt Defines how the 'TestAppExample' target should be installed. It specifies destinations for the executable, libraries, and bundles based on standard CMake installation directories. ```cmake install(TARGETS TestAppExample BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) ``` -------------------------------- ### Install CMake Config Files Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Installs the generated QtKeychainConfig.cmake and QtKeychainConfigVersion.cmake files. ```cmake install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain) ``` -------------------------------- ### Install qtkeychain with VCPKG on all platforms Source: https://github.com/frankosterfeld/qtkeychain/wiki/Home Installs qtkeychain using VCPKG, a cross-platform C++ package manager. ```powershell git clone https://github.com/microsoft/vcpkg .\vcpkg\bootstrap-vcpkg.bat .\vcpkg\vcpkg.exe install qtkeychain ``` -------------------------------- ### Install .pri File Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Installs the generated .pri file to the specified MKSPECS directory. ```cmake install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) ``` -------------------------------- ### Store Binary Data Example Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/OVERVIEW.md Demonstrates storing binary data, such as an API token, in the keychain. The data is provided as a QByteArray. ```cpp auto writeJob = new QKeychain::WritePasswordJob("myapp.service"); writeJob->setKey("apitoken"); writeJob->setBinaryData(QByteArray::fromHex("...")); writeJob->start(); ``` -------------------------------- ### Setup Version Variable Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Sets up version variables for the package config file using ecm_setup_version. ```cmake ecm_setup_version("${QTKEYCHAIN_VERSION}" VARIABLE_PREFIX SNORE PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake" SOVERSION ${QTKEYCHAIN_VERSION}) ``` -------------------------------- ### Store Password Example Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/OVERVIEW.md Shows how to store a password in the keychain for a given service and key. It also connects to the finished signal for error reporting. ```cpp auto writeJob = new QKeychain::WritePasswordJob("myapp.service"); writeJob->setKey("username"); writeJob->setTextData("mypassword"); writeJob->setAutoDelete(true); connect(writeJob, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() != QKeychain::NoError) { qDebug() << "Failed to store password:" << job->errorString(); } }); writeJob->start(); ``` -------------------------------- ### Compile qtkeychain on Ubuntu Linux Source: https://github.com/frankosterfeld/qtkeychain/wiki/Home Installs dependencies, clones the repository, and compiles the project using CMake. ```bash apt-get install git build-essential libqt4-dev cmake cd /usr/src git clone https://github.com/frankosterfeld/qtkeychain.git cd qtkeychain mkdir build cd build cmake .. make ``` -------------------------------- ### Check Backend Availability and Configure Fallback Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md This snippet demonstrates how to check if a secure backend is available and configure a fallback mechanism using QSettings if it's not. It shows the setup for both scenarios. ```cpp if (!QKeychain::isAvailable()) { qWarning() << "No secure backend available"; // Configure fallback QSettings settings("MyApp", "MyApp"); auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("password"); job->setSettings(&settings); job->setInsecureFallback(true); job->start(); } else { // Secure backend available, no fallback needed auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("password"); job->start(); } ``` -------------------------------- ### Install CMake Export Files Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Installs CMake export files for Qt Keychain library dependencies. ```cmake install(EXPORT Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain") ``` -------------------------------- ### Read Password Example Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/OVERVIEW.md Demonstrates how to read a password from the keychain for a specific service and key. Connects to the finished signal to handle success or error. ```cpp #include // Read a password auto readJob = new QKeychain::ReadPasswordJob("myapp.service"); readJob->setKey("username"); readJob->setAutoDelete(true); connect(readJob, &QKeychain::Job::finished, [readJob](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { QString password = static_cast(job)->textData(); qDebug() << "Password:" << password; } else { qDebug() << "Error:" << job->errorString(); } }); readJob->start(); ``` -------------------------------- ### Basic CMake Project Setup Source: https://github.com/frankosterfeld/qtkeychain/blob/main/TestAppExample/CMakeLists.txt Initializes the CMake build system, sets the minimum required version, and defines the project name and languages. This block is conditionally executed if QTKEYCHAIN_TARGET_NAME is not defined. ```cmake if(NOT DEFINED QTKEYCHAIN_TARGET_NAME) cmake_minimum_required(VERSION 3.16) project(TestAppExample LANGUAGES CXX) endif() ``` -------------------------------- ### Basic Secure Storage Example Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Demonstrates basic secure storage without fallback. The job will fail with `NoBackendAvailable` if no secure backend is present. `AutoDelete` is true by default. ```cpp auto writeJob = new QKeychain::WritePasswordJob("com.example.app"); writeJob->setKey("api_token"); writeJob->setTextData(apiToken); // AutoDelete: true (default) // Fallback: false (default) connect(writeJob, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qDebug() << "Stored securely"; } else if (job->error() == QKeychain::NoBackendAvailable) { qWarning() << "No secure backend available"; } }); writeJob->start(); ``` -------------------------------- ### Check Keychain Availability at Application Startup Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/functions.md This snippet demonstrates how to check if a secure keychain backend is available when your application starts. If not available, it logs a warning and exits. ```cpp int main(int argc, char **argv) { QCoreApplication app(argc, argv); if (!QKeychain::isAvailable()) { qWarning() << "No secure keychain backend available on this system."; qWarning() << "Credentials cannot be stored securely."; return 1; } // Continue with keychain operations return 0; } ``` -------------------------------- ### Delete Password Example Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/OVERVIEW.md Illustrates how to delete a password entry from the keychain using the service and key. Includes error handling via the finished signal. ```cpp auto deleteJob = new QKeychain::DeletePasswordJob("myapp.service"); deleteJob->setKey("username"); deleteJob->setAutoDelete(true); connect(deleteJob, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() != QKeychain::NoError) { qDebug() << "Failed to delete password:" << job->errorString(); } }); deleteJob->start(); ``` -------------------------------- ### Compile qtkeychain on MacOS Source: https://github.com/frankosterfeld/qtkeychain/wiki/Home Clones the repository and compiles using CMake on macOS, requiring Qt5 and CMake installation. ```bash git clone https://github.com/frankosterfeld/qtkeychain.git cd qtkeychain md build cd build cmake .. -DCMAKE_PREFIX_PATH=${QTDIR}/lib/cmake make ``` -------------------------------- ### Idempotent Delete Operation Example Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md Illustrates the idempotent nature of delete operations. Calling delete multiple times for the same key on the same service will not result in an error, even if the key has already been deleted. Ensure jobs are started within the Qt event loop. ```cpp // Both calls return NoError auto job1 = new QKeychain::DeletePasswordJob("service"); job1->setKey("key"); job1->start(); // ... later ... auto job2 = new QKeychain::DeletePasswordJob("service"); job2->setKey("key"); job2->start(); // Also returns NoError, even if already deleted ``` -------------------------------- ### Display Keychain Status to User Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/functions.md This example updates a UI label to inform the user about the availability of secure credential storage. It uses different text and styling based on whether a secure backend is present. ```cpp void SettingsDialog::showKeychainStatus() { if (QKeychain::isAvailable()) { statusLabel->setText("Secure credential storage available"); statusLabel->setStyleSheet("color: green;"); } else { statusLabel->setText("Warning: Credentials stored in plaintext"); statusLabel->setStyleSheet("color: orange;"); detailsLabel->setText( "Your system does not have a secure keychain backend. " "Consider installing GNOME Keyring or KWallet." ); } } ``` -------------------------------- ### Handle Job Completion and Errors Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md This example illustrates how to connect to the finished signal of a job to check for success or specific errors. It demonstrates checking the error() code and using errorString() for more details when an error occurs. ```cpp connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { // Success } else if (job->error() == QKeychain::EntryNotFound) { qWarning() << "Entry not found"; } }); ``` ```cpp if (job->error() != QKeychain::NoError) { qWarning() << "Operation failed:" << job->errorString(); } ``` -------------------------------- ### Delete Stored Credential with Fallback Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md This example shows how to delete a stored credential, with an option to fall back to less secure storage (like QSettings) if a secure backend is unavailable. It also demonstrates setting custom QSettings for storage. ```APIDOC ## DeletePasswordJob with Fallback and Custom Settings ### Description Deletes a stored password, with an option to use a fallback mechanism (like QSettings) if secure storage is not available. Allows specifying custom `QSettings` for fallback. ### Method `QKeychain::DeletePasswordJob(const QByteArray &service)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Usage Example ```cpp // Use custom QSettings for fallback QSettings settings("MyApp", "MyApp"); // Create a job to delete a credential for "myapp.service" auto job = new QKeychain::DeletePasswordJob("myapp.service"); // Set the key of the credential to delete job->setKey("api_token"); // Set the custom QSettings object for fallback storage job->setSettings(&settings); // Enable insecure fallback if no secure backend is available job->setInsecureFallback(true); // Enable auto-deletion of the job object after completion job->setAutoDelete(true); // Connect to the finished signal to handle the job's outcome connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qDebug() << "Credential removed"; } }); // Start the deletion job job->start(); ``` ### Response #### Success Response (NoError) - The credential associated with the service and key is deleted, potentially using a fallback mechanism. #### Response Example None (completion is signaled via the `finished` signal). ### Error Handling - `QKeychain::Job::error()` can be checked in the `finished` signal. - `setInsecureFallback(true)` enables deletion from `QSettings` if secure backends fail. ``` -------------------------------- ### Handle WritePasswordJob Errors Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/write-password-job.md Connect to the finished signal of a WritePasswordJob to handle potential errors. This example demonstrates checking for common error codes and logging detailed error strings. ```cpp connect(job, &QKeychain::Job::finished, [job](QKeychain::Job *) { switch (job->error()) { case QKeychain::NoError: qDebug() << "Password stored successfully"; break; case QKeychain::AccessDeniedByUser: qDebug() << "User denied keychain access"; break; case QKeychain::NoBackendAvailable: qDebug() << "No secure backend available"; break; default: qDebug() << "Error:" << job->errorString(); } }); ``` -------------------------------- ### Configure Fallback Based on Keychain Availability Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/functions.md This example shows how to conditionally enable insecure plaintext fallback for password reading jobs if a secure keychain backend is not available. It connects to the job's finished signal to process the result. ```cpp QSettings settings("MyApp", "MyApp"); auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("api_token"); job->setSettings(&settings); // Enable fallback if no secure backend if (!QKeychain::isAvailable()) { qWarning() << "No secure backend; using plaintext fallback"; job->setInsecureFallback(true); } else { job->setInsecureFallback(false); } connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { auto readJob = static_cast(job); useToken(readJob->textData()); } }); job->start(); ``` -------------------------------- ### Job::start() Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md Starts the asynchronous execution of the job. Jobs are processed in a First-In, First-Out (FIFO) order by the global JobExecutor. It is essential to connect to the `finished()` signal to receive notifications upon completion. This method should be invoked after all job parameters have been set and signals have been connected. ```APIDOC ## Job::start() ### Description Starts the job by enqueuing it with the global `JobExecutor`. Jobs are executed serially in FIFO order. The actual work begins asynchronously; you must connect to the `finished()` signal to be notified of completion. **Note:** You must call `start()` after setting up job parameters and connecting to signals. ### Method `void start()` ### Example ```cpp auto job = new QKeychain::ReadPasswordJob("myservice"); job->setKey("username"); connect(job, &QKeychain::Job::finished, this, &MyClass::onJobFinished); job->start(); // Enqueue the job ``` ``` -------------------------------- ### Delete Password Job Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md This example demonstrates how to create and start a DeletePasswordJob to remove a stored password associated with a specific service and key. It includes connecting to the finished signal to handle job completion and potential errors. ```APIDOC ## DeletePasswordJob ### Description Creates a job to delete a stored password for a given service. ### Method `QKeychain::DeletePasswordJob(const QByteArray &service)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Usage Example ```cpp // Create a new job to delete a password for "myapp.service" auto job = new QKeychain::DeletePasswordJob("myapp.service"); // Set the key of the password to delete job->setKey("session_token"); // Enable auto-deletion of the job object after completion job->setAutoDelete(true); // Connect to the finished signal to handle the job's outcome connect(job, &QKeychain::Job::finished, this, [this](QKeychain::Job *job) { if (job->error() != QKeychain::NoError) { qWarning() << "Warning: Failed to delete session token"; } // Continue logout regardless of deletion success this->completeLogout(); }); // Start the deletion job job->start(); ``` ### Response #### Success Response (NoError) - The password associated with the service and key is deleted. #### Response Example None (completion is signaled via the `finished` signal). ### Error Handling - `QKeychain::Job::error()` can be checked in the `finished` signal. - Common error codes are detailed in `../errors.md`. ``` -------------------------------- ### Delete a Password Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md Example of how to delete a specific password from the keychain using DeletePasswordJob. ```APIDOC ## Delete a Password This pattern demonstrates how to delete a specific password associated with a service. ### Usage 1. Create a `DeletePasswordJob` instance, providing the service name. 2. Use `setKey()` to specify the identifier of the secret to delete. 3. Optionally, set `setAutoDelete(true)` for automatic cleanup after the job finishes. 4. Connect to the `finished()` signal to handle the outcome (success or error). 5. Call `start()` to initiate the deletion process. ### Request Example ```cpp auto job = new QKeychain::DeletePasswordJob("com.example.app"); job->setKey("user_password"); job->setAutoDelete(true); connect(job, &QKeychain::Job::finished, this, [this](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qDebug() << "Password deleted"; } else { qDebug() << "Failed to delete:" << job->errorString(); } }); job->start(); ``` ``` -------------------------------- ### Add Test Application Subdirectory Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Includes the 'TestAppExample' subdirectory if BUILD_QTQUICK_DEMO is enabled. ```cmake if(BUILD_QTQUICK_DEMO) add_subdirectory(TestAppExample) endif() ``` -------------------------------- ### Log Keychain Backend Status at Application Startup Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/functions.md This snippet logs the QtKeychain version and whether a secure backend is available at application startup. This is useful for debugging and monitoring. ```cpp void Application::logStartupInfo() { qInfo() << "QtKeychain Version:" << QTKEYCHAIN_VERSION; qInfo() << "Secure backend available:" << (QKeychain::isAvailable() ? "Yes" : "No"); } ``` -------------------------------- ### Get Detailed Keychain Error Message Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/types.md Retrieves and logs a detailed error message when a keychain job fails. ```cpp if (job->error() != QKeychain::NoError) { QString details = job->errorString(); qWarning() << "Failed:" << details; } ``` -------------------------------- ### settings() Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md Retrieves the `QSettings` instance currently configured for plaintext fallback storage. Returns `nullptr` if no `QSettings` instance has been set. ```APIDOC ## settings() ### Description Returns the `QSettings` instance used for plaintext fallback storage. Returns `nullptr` if not set. ### Method QSettings * ### Returns - **QSettings***: A pointer to the `QSettings` instance, or `nullptr` if none is set. ### See also: - `setSettings()` - `setInsecureFallback()` ``` -------------------------------- ### setBinaryData() Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/write-password-job.md Sets the secret data to store as raw binary data. This method must be called before start() and is mutually exclusive with setTextData(). ```APIDOC ## setBinaryData() ```cpp void setBinaryData(const QByteArray &data) ``` ### Description Sets the secret data to store as raw binary data. ### Parameters #### Path Parameters - **data** (const QByteArray&) - Required - The binary data to store (e.g., encrypted keys, tokens, certificates) ### Prerequisites - Must be called before `start()` - Mutually exclusive with `setTextData()` — only one can be set per job ``` -------------------------------- ### setTextData() Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/write-password-job.md Sets the secret data to store as a UTF-8 encoded string. This method must be called before start() and is mutually exclusive with setBinaryData(). ```APIDOC ## setTextData() ```cpp void setTextData(const QString &data) ``` ### Description Sets the secret data to store as a UTF-8 encoded string. ### Parameters #### Path Parameters - **data** (const QString&) - Required - The text data to store (typically a password) ### Prerequisites - Must be called before `start()` - Mutually exclusive with `setBinaryData()` — only one can be set per job ``` -------------------------------- ### Job::setKey() Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md Sets the key that the job will use to identify a specific secret. This operation must be performed before calling `start()` for the key to be effective. ```APIDOC ## Job::setKey() ### Description Sets the key that this job will use to identify the secret. **Note:** This must be called before `start()` to have any effect. ### Method `void setKey(const QString &key)` ### Parameters #### Path Parameters - **key** (const QString&) - Description: The key name. Can be an empty string. ### Example ```cpp auto job = new QKeychain::WritePasswordJob("myservice"); job->setKey("database_password"); job->setTextData("secret123"); job->start(); ``` ``` -------------------------------- ### Executable Definition for Qt6 Source: https://github.com/frankosterfeld/qtkeychain/blob/main/TestAppExample/CMakeLists.txt Defines the main executable target 'TestAppExample' using Qt6-specific commands. It lists the source files, including generated resources, and requires manual finalization. ```cmake if(NOT BUILD_WITH_QT5) qt_add_executable(TestAppExample MANUAL_FINALIZATION keychainclass.h keychainclass.cpp main.cpp ${QT_RESOURCES} ) else() add_executable(TestAppExample keychainclass.h keychainclass.cpp main.cpp ${QT_RESOURCES} ) endif() ``` -------------------------------- ### Configure ReadPasswordJob with Manual Deletion Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Example of a ReadPasswordJob configured with auto-delete disabled. The job must be manually deleted after the 'finished' signal is processed. ```cpp auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("password"); job->setAutoDelete(false); // Keep alive after finished() connect(job, &QKeychain::Job::finished, [job](QKeychain::Job *) { QString password = job->textData(); qDebug() << password; // Job still exists; need to delete manually job->deleteLater(); }); job->start(); ``` -------------------------------- ### Enable Insecure Fallback for NoBackendAvailable Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/errors.md Shows how to configure a job to fall back to using plaintext QSettings if no secure keychain backend is available. This is useful for ensuring operations can proceed even on unsupported platforms. ```cpp QSettings settings("MyApp", "MyApp"); auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("password"); job->setSettings(&settings); job->setInsecureFallback(true); // Fall back to plaintext QSettings connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { // Now will attempt plaintext fallback if no secure backend // May still return NoError (with plaintext data) }); job->start(); ``` -------------------------------- ### Configure ReadPasswordJob with Auto-Delete Enabled Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Example of a ReadPasswordJob configured with auto-delete enabled (default behavior). The job will delete itself after the 'finished' signal is emitted. ```cpp auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("password"); job->setAutoDelete(true); // Default connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { auto readJob = static_cast(job); qDebug() << readJob->textData(); // Job will be deleted shortly after this lambda returns }); job->start(); ``` -------------------------------- ### Configure Package Config File Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Generates the QtKeychainConfig.cmake file from a template. ```cmake configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/QtKeychainConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake" INSTALL_DESTINATION Qt${QTKEYCHAIN_VERSION_INFIX}Keychain) ``` -------------------------------- ### Store Password with Insecure Fallback Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/INDEX.md Demonstrates how to store a password using QKeychain, with an option to fall back to insecure plaintext storage if a secure backend is unavailable. Requires QSettings for fallback. ```cpp QSettings settings("MyApp", "MyApp"); auto job = new QKeychain::WritePasswordJob("com.example.app"); job->setKey("token"); job->setTextData("value"); job->setSettings(&settings); job->setInsecureFallback(true); job->start(); ``` -------------------------------- ### Linking Libraries Source: https://github.com/frankosterfeld/qtkeychain/blob/main/TestAppExample/CMakeLists.txt Links the 'TestAppExample' target against the necessary Qt modules and the determined QtKeychain target. This makes the functionality of these libraries available to the application. ```cmake target_link_libraries(TestAppExample PRIVATE ${QTx}::Core ${QTx}::Network ${QTx}::Quick ${QTx}::Qml ${KEYCHAIN_TARGET}) ``` -------------------------------- ### Set Text Data for Storage Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/write-password-job.md Use setTextData to store a secret as a UTF-8 encoded string. This method is mutually exclusive with setBinaryData and must be called before starting the job. ```cpp auto job = new QKeychain::WritePasswordJob("myapp"); job->setKey("user_password"); job->setTextData("mySecurePassword123!"); job->start(); ``` -------------------------------- ### Compile qtkeychain on Windows Source: https://github.com/frankosterfeld/qtkeychain/wiki/Home Builds the project on Windows using CMake, assuming Qt5 and environment variables are set. ```batch mkdir build cd build cmake .. -DCMAKE_PREFIX_PATH=%QTDIR%\lib\cmake cmake --build . ``` -------------------------------- ### Delete Password on User Logout Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md Use this snippet to delete a stored password when a user logs out of an application. Ensure the job is created and started within the Qt event loop. ```cpp void MyApp::onUserLogout() { auto job = new QKeychain::DeletePasswordJob("myapp.service"); job->setKey("session_token"); job->setAutoDelete(true); connect(job, &QKeychain::Job::finished, this, [this](QKeychain::Job *job) { if (job->error() != QKeychain::NoError) { qWarning() << "Warning: Failed to delete session token"; } // Continue logout regardless of deletion success this->completeLogout(); }); job->start(); } ``` -------------------------------- ### Glob for Source Files Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Finds all .cpp, .h, and .ui files within the qtkeychain directory. ```cmake file(GLOB qtkeychain_TR_SOURCES qtkeychain/*.cpp qtkeychain/*.h qtkeychain/*.ui) ``` -------------------------------- ### Store Binary Data with Custom QSettings Path Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Stores binary data securely, with an option for plaintext fallback using a custom QSettings instance configured with a specific format and path. `AutoDelete` is set to true. ```cpp // Use app-specific directory for QSettings QSettings settings( QSettings::IniFormat, QSettings::UserScope, "MyCompany", "MyApp" ); QByteArray encryptedKey = getEncryptionKey(); auto job = new QKeychain::WritePasswordJob("com.example.app"); job->setKey("encryption_key"); job->setBinaryData(encryptedKey); job->setSettings(&settings); job->setInsecureFallback(true); job->setAutoDelete(true); connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qDebug() << "Encryption key stored"; } }); job->start(); ``` -------------------------------- ### Retrieve Text Data with ReadPasswordJob Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/read-password-job.md After a successful job completion, use textData() to get the retrieved secret as a UTF-8 decoded string. Ensure the data was originally stored as text. ```cpp auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("username"); connect(job, &QKeychain::Job::finished, [job](QKeychain::Job *) { if (job->error() == QKeychain::NoError) { QString password = job->textData(); qDebug() << "Password:" << password; } }); job->start(); ``` -------------------------------- ### Check Backend Availability Before Operation Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/errors.md Provides a simple check for the availability of a secure backend using `QKeychain::isAvailable()`. This allows applications to proactively inform users or adjust behavior if no secure backend is present. ```cpp if (!QKeychain::isAvailable()) { qWarning() << "No secure backend. Consider enabling fallback or warning user."; } ``` -------------------------------- ### QtKeychain Dependency Management Source: https://github.com/frankosterfeld/qtkeychain/blob/main/TestAppExample/CMakeLists.txt Handles the inclusion of the QtKeychain library. It supports adding it as a subdirectory for development or finding an installed version. The target name for QtKeychain is determined based on the Qt version. ```cmake if(DEFINED QTKEYCHAIN_TARGET_NAME) # Included as subdirectory from the top-level build (BUILD_QTQUICK_DEMO=ON) set(KEYCHAIN_TARGET ${QTKEYCHAIN_TARGET_NAME}) else() # Standalone build: pull in the library from source (one level up) get_filename_component(_qtkeychain_source_dir "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE) if(EXISTS "${_qtkeychain_source_dir}/qtkeychain/keychain.h") add_subdirectory("${_qtkeychain_source_dir}" "${CMAKE_CURRENT_BINARY_DIR}/qtkeychain_build") # QTKEYCHAIN_TARGET_NAME is set inside the subdirectory scope, derive it here if(BUILD_WITH_QT5) set(KEYCHAIN_TARGET qt5keychain) else() set(KEYCHAIN_TARGET qt6keychain) endif() else() # Fallback: find an already-installed QtKeychain find_package(${QTx}Keychain REQUIRED) set(KEYCHAIN_TARGET ${QTx}Keychain::${QTx}Keychain) endif() endif() ``` -------------------------------- ### Complete Keychain Initialization with Fallback Logic Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/functions.md This function provides a comprehensive initialization pattern for QtKeychain. It checks for backend availability and configures plaintext fallback specifically for debug builds if no secure backend is found, while failing in production. ```cpp bool initializeKeychain() { qDebug() << "Initializing keychain..."; // Check if secure backend is available bool secureAvailable = QKeychain::isAvailable(); qDebug() << "Secure backend available:" << secureAvailable; if (!secureAvailable) { // Configure fallback for development/testing #ifdef QT_DEBUG qWarning() << "Running in debug mode without secure backend."; qWarning() << "Credentials will be stored plaintext."; return true; // Continue in debug mode #else qCritical() << "No secure backend available in production!"; qCritical() << "Please install GNOME Keyring, KWallet, or libsecret."; return false; // Fail in production #endif } qDebug() << "Keychain ready."; return true; } ``` -------------------------------- ### Set Binary Data for Storage Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/write-password-job.md Use setBinaryData to store raw binary data, such as encrypted keys or certificates. This method is mutually exclusive with setTextData and must be called before starting the job. ```cpp auto job = new QKeychain::WritePasswordJob("myapp"); job->setKey("encryption_key"); QByteArray encryptedKey = generateEncryptionKey(); job->setBinaryData(encryptedKey); job->start(); ``` -------------------------------- ### setSettings() Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md Sets a `QSettings` instance to be used for plaintext fallback storage when `insecureFallback()` is enabled. This method is crucial for enabling insecure fallback behavior. ```APIDOC ## setSettings() ### Description Sets the `QSettings` instance to use for plaintext fallback storage (when `insecureFallback()` is true). ### Method void ### Parameters #### Path Parameters - **settings** (QSettings*) - Required - A QSettings instance for plaintext storage. Can be nullptr to disable. ### Note: This has no effect unless `setInsecureFallback(true)` is also called. ### Example: ```cpp QSettings *appSettings = new QSettings("Company", "MyApp", this); auto job = new QKeychain::ReadPasswordJob("myservice"); job->setSettings(appSettings); job->setInsecureFallback(true); job->setKey("username"); job->start(); ``` ``` -------------------------------- ### Build Test Client Application Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Configures and builds the 'testclient' executable if BUILD_TEST_APPLICATION is enabled. Includes platform-specific libraries for macOS. ```cmake if(BUILD_TEST_APPLICATION) set( testclient_LIBRARIES ${QTKEYCHAIN_TARGET_NAME} ) if(APPLE) list(APPEND testclient_LIBRARIES "-framework Cocoa") find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Gui REQUIRED) list(APPEND testclient_LIBRARIES Qt${QT_MAJOR_VERSION}::Gui) endif() add_executable( testclient testclient.cpp ) target_link_libraries( testclient ${testclient_LIBRARIES}) endif() ``` -------------------------------- ### Secure Storage with Fallback for Development Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Configures a job to use secure storage but fall back to plaintext using a provided QSettings object if no secure backend is available. `AutoDelete` is set to true. ```cpp QSettings devSettings("MyApp", "MyApp-Dev"); auto job = new QKeychain::ReadPasswordJob("com.example.app"); job->setKey("database_password"); job->setSettings(&devSettings); job->setInsecureFallback(true); job->setAutoDelete(true); connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { auto readJob = static_cast(job); connectToDB(readJob->textData()); } }); job->start(); ``` -------------------------------- ### Include QtKeychain Header Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/INDEX.md Include the main QtKeychain header file to use its functionalities. ```cpp #include ``` -------------------------------- ### Set Key for a Write Password Job Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md This snippet shows how to set a specific key for a WritePasswordJob and provide the text data to be stored. The key identifies the secret within the service, and setKey must be called before start(). ```cpp auto job = new QKeychain::WritePasswordJob("myservice"); job->setKey("database_password"); job->setTextData("secret123"); job->start(); ``` -------------------------------- ### Generate .pri File Source: https://github.com/frankosterfeld/qtkeychain/blob/main/CMakeLists.txt Generates a .pri file for Qt, including core dependencies and platform-specific extras. ```cmake ecm_generate_pri_file(BASE_NAME Qt${QTKEYCHAIN_VERSION_INFIX}Keychain LIB_NAME ${QTKEYCHAIN_TARGET_NAME} DEPS "core ${PRI_EXTRA_DEPS}" INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} FILENAME_VAR pri_filename) ``` -------------------------------- ### Usage Pattern: Delete a Specific Password Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md Demonstrates the complete process of deleting a specific password using DeletePasswordJob, including setting the service, key, enabling auto-deletion, connecting to the finished signal, and starting the job. ```cpp auto job = new QKeychain::DeletePasswordJob("com.example.app"); job->setKey("user_password"); job->setAutoDelete(true); connect(job, &QKeychain::Job::finished, this, [this](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qDebug() << "Password deleted"; } else { qDebug() << "Failed to delete:" << job->errorString(); } }); job->start(); ``` -------------------------------- ### Set Key and Binary Data for WritePasswordJob Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Illustrates setting a key and binary data for a WritePasswordJob. Binary data is stored as raw bytes and is mutually exclusive with text data. ```cpp QByteArray encryptedKey = generateEncryption(); auto job = new QKeychain::WritePasswordJob("myapp"); job->setKey("master_key"); job->setBinaryData(encryptedKey); job->start(); ``` -------------------------------- ### Connect to Job Finished Signal Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/job.md Connects to the `finished()` signal to handle job completion. It's crucial to check `job->error()` to determine success or failure and to manage job deletion if `autoDelete()` is false. Always connect before calling `start()`. ```cpp auto job = new QKeychain::ReadPasswordJob("myservice"); job->setKey("username"); connect(job, &QKeychain::Job::finished, this, [this](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { auto readJob = static_cast(job); qDebug() << "Password:" << readJob->textData(); } else { qDebug() << "Error:" << job->errorString(); } }); job->start(); ``` -------------------------------- ### isAvailable() Function Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/MANIFEST.txt Documentation for the free function `isAvailable()`, which checks if the QtKeychain service is available on the current platform. ```APIDOC ## isAvailable() Function ### Description The `isAvailable()` function is a utility that checks whether the QtKeychain library can access a secure storage backend on the current operating system. ### `isAvailable()` Documentation Details on the function's return value and purpose. ### Platform-Specific Behavior Information on how the availability check is performed on different operating systems. ### Usage Patterns Examples of how to use `isAvailable()` to conditionally enable or disable keychain functionality. ### Integration with Configuration How `isAvailable()` relates to the overall configuration of QtKeychain. ### Initialization Patterns Recommended patterns for calling `isAvailable()` during application startup. ``` -------------------------------- ### Create a ReadPasswordJob Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/read-password-job.md Instantiate a ReadPasswordJob to begin the process of retrieving a secret. Specify the service namespace and optionally a Qt parent object. The key for the specific secret is set separately. ```cpp auto readJob = new QKeychain::ReadPasswordJob("com.example.myapp"); readJob->setKey("api_token"); readJob->start(); ``` -------------------------------- ### Usage Pattern: Clear All Credentials for a Service Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/delete-password-job.md Illustrates how to clear all credentials for a given service by iterating through a list of known keys and initiating a separate DeletePasswordJob for each key. ```cpp QStringList keysToDelete = {"api_token", "user_password", "refresh_token"}; for (const QString &key : keysToDelete) { auto job = new QKeychain::DeletePasswordJob("myapp.service"); job->setKey(key); connect(job, &QKeychain::Job::finished, [key](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qDebug() << "Deleted" << key; } }); job->start(); } ``` -------------------------------- ### Read Password Job with Non-existent Key Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/types.md Demonstrates a scenario where `EntryNotFound` is returned when attempting to read a password for a key that does not exist. ```cpp auto job = new QKeychain::ReadPasswordJob("myapp.service"); job->setKey("nonexistent_key"); connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { // job->error() == QKeychain::EntryNotFound // job->textData() and job->binaryData() return empty }); job->start(); ``` -------------------------------- ### Set Key and Text Data for WritePasswordJob Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Demonstrates setting a key and text data for a WritePasswordJob. Text data is stored as UTF-8 encoded string. ```cpp auto job = new QKeychain::WritePasswordJob("myapp"); job->setKey("user_password"); job->setTextData("securePassword123"); job->start(); ``` -------------------------------- ### Create WritePasswordJob Instance Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/api-reference/write-password-job.md Instantiate a WritePasswordJob to store a secret for a specific service. The service acts as a namespace for related secrets. ```cpp auto writeJob = new QKeychain::WritePasswordJob("com.example.myapp"); writeJob->setKey("api_token"); writeJob->setTextData("token123456"); writeJob->start(); ``` -------------------------------- ### Handle Entry Not Found Error Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/errors.md This code demonstrates how to detect and handle the `EntryNotFound` error, which occurs when a requested secret does not exist in the keychain. It suggests prompting the user for authentication and then writing the new entry. ```cpp auto job = new QKeychain::ReadPasswordJob("myapp"); job->setKey("api_token"); connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::EntryNotFound) { qWarning() << "API token not found. Prompt user to authenticate."; } }); job->start(); ``` ```cpp auto readJob = static_cast(job); if (readJob->error() == QKeychain::EntryNotFound) { // Prompt user to set password or authenticate QString password = promptUserForPassword(); // Then store it for future use auto writeJob = new QKeychain::WritePasswordJob("myapp"); writeJob->setKey("api_token"); writeJob->setTextData(password); writeJob->start(); } ``` -------------------------------- ### C++ Standard and Qt Build Settings Source: https://github.com/frankosterfeld/qtkeychain/blob/main/TestAppExample/CMakeLists.txt Enables C++11 standard and configures Qt's automatic processing for MOC, RCC, and UIC. It also sets up a bundle identifier and an option to select between Qt5 and Qt6. ```cmake SET(CMAKE_CXX_STANDARD 11) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) set(BUNDLE_IDENTIFIER "org.qtkeychain.TestAppExample") option(BUILD_WITH_QT5 "Build qtkeychain with Qt 5 (default is Qt 6)" OFF) if (BUILD_WITH_QT5) set(QTx Qt5) else() set(QTx Qt6) endif() ``` -------------------------------- ### Fallback Behavior with Plaintext Storage Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/types.md Configures a keychain job to use `QSettings` for plaintext storage as a fallback when no secure backend is available. This can prevent `NoBackendAvailable` errors. ```cpp QSettings settings("MyApp", "MyApp"); auto job = new QKeychain::ReadPasswordJob("myapp.service"); job->setKey("token"); job->setSettings(&settings); job->setInsecureFallback(true); connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { // If no secure backend and fallback configured: // - Will attempt plaintext QSettings read // - May return NoError or EntryNotFound (not NoBackendAvailable) }); job->start(); ``` -------------------------------- ### Find Qt Components Source: https://github.com/frankosterfeld/qtkeychain/blob/main/TestAppExample/CMakeLists.txt Locates and makes the necessary Qt components (Core, Network, Quick, Qml) available for the project. This is required for building Qt applications. ```cmake find_package(${QTx} COMPONENTS Core Network Quick Qml REQUIRED) ``` -------------------------------- ### Write Password with Logging Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/errors.md Writes a password to the secure backend and logs success or failure. Failed writes include detailed error information and can be logged to external monitoring services. ```cpp auto job = new QKeychain::WritePasswordJob("myapp"); job->setKey("api_token"); job->setTextData(token); connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qInfo() << "API token stored successfully"; } else { qWarning() << "Failed to store API token" << "Error:" << job->error() << "Details:" << job->errorString(); // Log to analytics/monitoring logToMonitoring("keychain_store_failed", job->errorString()); } }); job->start(); ``` -------------------------------- ### Configure QSettings for Plaintext Fallback Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Sets a custom QSettings instance for plaintext storage when fallback is enabled. The lifetime of this QSettings object must exceed the job's lifetime. This is required if `setInsecureFallback(true)` is used. ```cpp // Create persistent settings object QSettings *appSettings = new QSettings("MyCompany", "MyApp", this); auto readJob = new QKeychain::ReadPasswordJob("myapp"); readJob->setKey("api_token"); readJob->setSettings(appSettings); readJob->setInsecureFallback(true); connect(readJob, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { auto rj = static_cast(job); qDebug() << "Token:" << rj->textData(); } }); readJob->start(); ``` -------------------------------- ### Enable Plaintext Fallback Storage Source: https://github.com/frankosterfeld/qtkeychain/blob/main/_autodocs/configuration.md Enables storing data in plaintext using QSettings if no secure backend is available. WARNING: This provides no security and should only be used for development or non-sensitive data. Requires `setSettings()` to be called first. ```cpp QSettings settings("MyApp", "MyApp"); auto job = new QKeychain::WritePasswordJob("myapp"); job->setKey("dev_token"); job->setTextData("dev_token_value"); job->setSettings(&settings); job->setInsecureFallback(true); // WARNING: Stores plaintext if needed connect(job, &QKeychain::Job::finished, [](QKeychain::Job *job) { if (job->error() == QKeychain::NoError) { qDebug() << "Stored (secure or plaintext fallback)"; } }); job->start(); ```