mirror of
https://github.com/danbulant/dots-hyprland
synced 2026-05-24 12:22:09 +00:00
119 lines
4 KiB
QML
119 lines
4 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
import "root:/"
|
|
import "root:/modules/common"
|
|
import "root:/modules/common/functions/string_utils.js" as StringUtils
|
|
import Quickshell;
|
|
import Quickshell.Io;
|
|
import Qt.labs.platform
|
|
import QtQuick;
|
|
|
|
/**
|
|
* For storing sensitive data in the keyring.
|
|
* Use this for small data only, since it stores a JSON of the contents directly and doesn't use a database.
|
|
*/
|
|
Singleton {
|
|
id: root
|
|
|
|
property bool loaded: false
|
|
property var keyringData: ({})
|
|
|
|
property var properties: {
|
|
"application": "illogical-impulse",
|
|
"explanation": Translation.tr("For storing API keys and other sensitive information"),
|
|
}
|
|
property var propertiesAsArgs: Object.keys(root.properties).reduce(
|
|
function(arr, key) {
|
|
return arr.concat([key, root.properties[key]]);
|
|
}, []
|
|
)
|
|
property string keyringLabel: StringUtils.format(Translation.tr("{0} Safe Storage"), "illogical-impulse")
|
|
|
|
function setNestedField(path, value) {
|
|
if (!root.keyringData) root.keyringData = {};
|
|
let keys = path;
|
|
let obj = root.keyringData;
|
|
let parents = [obj];
|
|
|
|
// Traverse and collect parent objects
|
|
for (let i = 0; i < keys.length - 1; ++i) {
|
|
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") {
|
|
obj[keys[i]] = {};
|
|
}
|
|
obj = obj[keys[i]];
|
|
parents.push(obj);
|
|
}
|
|
|
|
// Set the value at the innermost key
|
|
obj[keys[keys.length - 1]] = value;
|
|
|
|
// Reassign each parent object from the bottom up to trigger change notifications
|
|
for (let i = keys.length - 2; i >= 0; --i) {
|
|
let parent = parents[i];
|
|
let key = keys[i];
|
|
// Shallow clone to change object identity (spread replaced with Object.assign)
|
|
parent[key] = Object.assign({}, parent[key]);
|
|
}
|
|
|
|
// Finally, reassign root.keyringData to trigger top-level change
|
|
root.keyringData = Object.assign({}, root.keyringData);
|
|
|
|
saveKeyringData();
|
|
}
|
|
|
|
function fetchKeyringData() {
|
|
// console.log("[KeyringStorage] Fetching keyring data...");
|
|
// console.log("[KeyringStorage] getData command:'" + getData.command.join("' '") + "'");
|
|
getData.running = true;
|
|
}
|
|
|
|
function saveKeyringData() {
|
|
saveData.stdinEnabled = true;
|
|
saveData.running = true;
|
|
}
|
|
|
|
Process {
|
|
id: saveData
|
|
command: [
|
|
"secret-tool", "store", "--label=" + keyringLabel,
|
|
...propertiesAsArgs,
|
|
]
|
|
onRunningChanged: {
|
|
if (saveData.running) {
|
|
// console.log("[KeyringStorage] Saving with command: '" + saveData.command.join("' '") + "'");
|
|
saveData.write(JSON.stringify(root.keyringData));
|
|
stdinEnabled = false // End input stream
|
|
}
|
|
}
|
|
}
|
|
|
|
Process {
|
|
id: getData
|
|
command: [ // We need to use echo for a newline so splitparser does parse
|
|
"bash", "-c", `echo $(secret-tool lookup 'application' 'illogical-impulse')`,
|
|
]
|
|
stdout: SplitParser {
|
|
onRead: data => {
|
|
if(data.length === 0) return;
|
|
try {
|
|
root.keyringData = JSON.parse(data);
|
|
// console.log("[KeyringStorage] Keyring data fetched:", JSON.stringify(root.keyringData));
|
|
} catch (e) {
|
|
console.error("[KeyringStorage] Failed to get keyring data, reinitializing.");
|
|
root.keyringData = {};
|
|
saveKeyringData()
|
|
}
|
|
}
|
|
}
|
|
onExited: (exitCode, exitStatus) => {
|
|
// console.log("[KeyringStorage] Keyring data fetch process exited with code:", exitCode);
|
|
if (exitCode !== 0) {
|
|
console.error("[KeyringStorage] Failed to get keyring data, reinitializing.");
|
|
root.keyringData = {};
|
|
saveKeyringData()
|
|
}
|
|
root.loaded = true;
|
|
}
|
|
}
|
|
|
|
}
|