mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Reset password through setup wizard (#1490)
* closes FE portion of #1470 * remove accidental commit of local script * add reset password option (#1560) * fix error code for incorrect password and clarify codes with comments Co-authored-by: Matt Hill <matthill@Matt-M1.local> Co-authored-by: Lucy Cifferello <12953208+elvece@users.noreply.github.com> Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,3 +11,5 @@
|
|||||||
deploy_web.sh
|
deploy_web.sh
|
||||||
libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin
|
libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin
|
||||||
libs/js_engine/src/artifacts/JS_SNAPSHOT.bin
|
libs/js_engine/src/artifacts/JS_SNAPSHOT.bin
|
||||||
|
deploy_web.sh
|
||||||
|
secrets.db
|
||||||
|
|||||||
@@ -1,47 +1,46 @@
|
|||||||
{
|
{
|
||||||
"db": "SQLite",
|
"db": "SQLite",
|
||||||
"10350f5a16f1b2a6ce91672ae5dc6acc46691bd8f901861545ec83c326a8ccef": {
|
"10350f5a16f1b2a6ce91672ae5dc6acc46691bd8f901861545ec83c326a8ccef": {
|
||||||
"query": "INSERT INTO ssh_keys (fingerprint, openssh_pubkey, created_at) VALUES (?, ?, ?)",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 3
|
"Right": 3
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT INTO ssh_keys (fingerprint, openssh_pubkey, created_at) VALUES (?, ?, ?)"
|
||||||
|
},
|
||||||
"118d59de5cf930d5a3b5667b2220e9a3d593bd84276beb2b76c93b2694b0fd72": {
|
"118d59de5cf930d5a3b5667b2220e9a3d593bd84276beb2b76c93b2694b0fd72": {
|
||||||
"query": "INSERT INTO session (id, user_agent, metadata) VALUES (?, ?, ?)",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 3
|
"Right": 3
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT INTO session (id, user_agent, metadata) VALUES (?, ?, ?)"
|
||||||
|
},
|
||||||
"165daa7d6a60cb42122373b2c5ac7d39399bcc99992f0002ee7bfef50a8daceb": {
|
"165daa7d6a60cb42122373b2c5ac7d39399bcc99992f0002ee7bfef50a8daceb": {
|
||||||
"query": "DELETE FROM certificates WHERE id = 0 OR id = 1;",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 0
|
"Right": 0
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "DELETE FROM certificates WHERE id = 0 OR id = 1;"
|
||||||
|
},
|
||||||
"177c4b9cc7901a3b906e5969b86b1c11e6acbfb8e86e98f197d7333030b17964": {
|
"177c4b9cc7901a3b906e5969b86b1c11e6acbfb8e86e98f197d7333030b17964": {
|
||||||
"query": "DELETE FROM notifications WHERE id = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "DELETE FROM notifications WHERE id = ?"
|
||||||
|
},
|
||||||
"1b2242afa55e730b37b00929b656d80940b457ec86c234ddd0de917bd8872611": {
|
"1b2242afa55e730b37b00929b656d80940b457ec86c234ddd0de917bd8872611": {
|
||||||
"query": "INSERT INTO cifs_shares (hostname, path, username, password) VALUES (?, ?, ?, ?) RETURNING id AS \"id: u32\"",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -50,36 +49,36 @@
|
|||||||
"type_info": "Int64"
|
"type_info": "Int64"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 4
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 4
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT INTO cifs_shares (hostname, path, username, password) VALUES (?, ?, ?, ?) RETURNING id AS \"id: u32\""
|
||||||
|
},
|
||||||
"1eee1fdc793919c391008854407143d7a11b4668486c11a760b49af49992f9f8": {
|
"1eee1fdc793919c391008854407143d7a11b4668486c11a760b49af49992f9f8": {
|
||||||
"query": "REPLACE INTO tor (package, interface, key) VALUES (?, 'main', ?)",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 2
|
"Right": 2
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "REPLACE INTO tor (package, interface, key) VALUES (?, 'main', ?)"
|
||||||
|
},
|
||||||
"2932aa02735b6422fca4ba889abfb3de8598178d4690076dc278898753d9df62": {
|
"2932aa02735b6422fca4ba889abfb3de8598178d4690076dc278898753d9df62": {
|
||||||
"query": "UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = ?"
|
||||||
|
},
|
||||||
"3502e58f2ab48fb4566d21c920c096f81acfa3ff0d02f970626a4dcd67bac71d": {
|
"3502e58f2ab48fb4566d21c920c096f81acfa3ff0d02f970626a4dcd67bac71d": {
|
||||||
"query": "SELECT tor_key FROM account",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -88,16 +87,16 @@
|
|||||||
"type_info": "Blob"
|
"type_info": "Blob"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT tor_key FROM account"
|
||||||
|
},
|
||||||
"3e57a0e52b69f33e9411c13b03a5d82c5856d63f0375eb4c23b255a09c54f8b1": {
|
"3e57a0e52b69f33e9411c13b03a5d82c5856d63f0375eb4c23b255a09c54f8b1": {
|
||||||
"query": "SELECT key FROM tor WHERE package = ? AND interface = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -106,16 +105,16 @@
|
|||||||
"type_info": "Blob"
|
"type_info": "Blob"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT key FROM tor WHERE package = ? AND interface = ?"
|
||||||
|
},
|
||||||
"4691e3a2ce80b59009ac17124f54f925f61dc5ea371903e62cdffa5d7b67ca96": {
|
"4691e3a2ce80b59009ac17124f54f925f61dc5ea371903e62cdffa5d7b67ca96": {
|
||||||
"query": "SELECT * FROM session WHERE logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -149,9 +148,6 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@@ -159,51 +155,54 @@
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT * FROM session WHERE logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP"
|
||||||
|
},
|
||||||
"530192a2a530ee6b92e5b98e1eb1bf6d1426c7b0cb2578593a367cb0bf2c3ca8": {
|
"530192a2a530ee6b92e5b98e1eb1bf6d1426c7b0cb2578593a367cb0bf2c3ca8": {
|
||||||
"query": "UPDATE certificates SET priv_key_pem = ?, certificate_pem = ?, updated_at = datetime('now') WHERE lookup_string = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 3
|
"Right": 3
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "UPDATE certificates SET priv_key_pem = ?, certificate_pem = ?, updated_at = datetime('now') WHERE lookup_string = ?"
|
||||||
|
},
|
||||||
"56b986f2a2b7091d9c3acdd78f75d9842242de1f4da8f3672f2793d9fb256928": {
|
"56b986f2a2b7091d9c3acdd78f75d9842242de1f4da8f3672f2793d9fb256928": {
|
||||||
"query": "DELETE FROM tor WHERE package = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "DELETE FROM tor WHERE package = ?"
|
||||||
|
},
|
||||||
"5b114c450073f77f466c980a2541293f30087b57301c379630326e5e5c2fb792": {
|
"5b114c450073f77f466c980a2541293f30087b57301c379630326e5e5c2fb792": {
|
||||||
"query": "REPLACE INTO tor (package, interface, key) VALUES (?, ?, ?)",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 3
|
"Right": 3
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "REPLACE INTO tor (package, interface, key) VALUES (?, ?, ?)"
|
||||||
|
},
|
||||||
"5c47da44b9c84468e95a13fc47301989900f130b3b5899d1ee6664df3ed812ac": {
|
"5c47da44b9c84468e95a13fc47301989900f130b3b5899d1ee6664df3ed812ac": {
|
||||||
"query": "INSERT INTO certificates (id, priv_key_pem, certificate_pem, lookup_string, created_at, updated_at) VALUES (0, ?, ?, NULL, datetime('now'), datetime('now'))",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 2
|
"Right": 2
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT INTO certificates (id, priv_key_pem, certificate_pem, lookup_string, created_at, updated_at) VALUES (0, ?, ?, NULL, datetime('now'), datetime('now'))"
|
||||||
|
},
|
||||||
"629be61c3c341c131ddbbff0293a83dbc6afd07cae69d246987f62cf0cc35c2a": {
|
"629be61c3c341c131ddbbff0293a83dbc6afd07cae69d246987f62cf0cc35c2a": {
|
||||||
"query": "SELECT password FROM account",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -212,36 +211,36 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT password FROM account"
|
||||||
|
},
|
||||||
"63785dc5f193ea31e6f641a910c75857ccd288a3f6e9c4f704331531e4f0689f": {
|
"63785dc5f193ea31e6f641a910c75857ccd288a3f6e9c4f704331531e4f0689f": {
|
||||||
"query": "UPDATE session SET last_active = CURRENT_TIMESTAMP WHERE id = ? AND logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "UPDATE session SET last_active = CURRENT_TIMESTAMP WHERE id = ? AND logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP"
|
||||||
|
},
|
||||||
"6440354d73a67c041ea29508b43b5f309d45837a44f1a562051ad540d894c7d6": {
|
"6440354d73a67c041ea29508b43b5f309d45837a44f1a562051ad540d894c7d6": {
|
||||||
"query": "DELETE FROM ssh_keys WHERE fingerprint = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "DELETE FROM ssh_keys WHERE fingerprint = ?"
|
||||||
|
},
|
||||||
"65e6c3fbb138da5cf385af096fdd3c062b6e826e12a8a4b23e16fcc773004c29": {
|
"65e6c3fbb138da5cf385af096fdd3c062b6e826e12a8a4b23e16fcc773004c29": {
|
||||||
"query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications WHERE id < ? ORDER BY id DESC LIMIT ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -285,9 +284,6 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
@@ -297,11 +293,14 @@
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications WHERE id < ? ORDER BY id DESC LIMIT ?"
|
||||||
|
},
|
||||||
"668f39c868f90cdbcc635858bac9e55ed73192ed2aec5c52dcfba9800a7a4a41": {
|
"668f39c868f90cdbcc635858bac9e55ed73192ed2aec5c52dcfba9800a7a4a41": {
|
||||||
"query": "SELECT id AS \"id: u32\", hostname, path, username, password FROM cifs_shares",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -330,30 +329,30 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT id AS \"id: u32\", hostname, path, username, password FROM cifs_shares"
|
||||||
|
},
|
||||||
"6b9abc9e079cff975f8a7f07ff70548c7877ecae3be0d0f2d3f439a6713326c0": {
|
"6b9abc9e079cff975f8a7f07ff70548c7877ecae3be0d0f2d3f439a6713326c0": {
|
||||||
"query": "DELETE FROM notifications WHERE id < ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "DELETE FROM notifications WHERE id < ?"
|
||||||
|
},
|
||||||
"6c96d76bffcc5f03290d8d8544a58521345ed2a843a509b17bbcd6257bb81821": {
|
"6c96d76bffcc5f03290d8d8544a58521345ed2a843a509b17bbcd6257bb81821": {
|
||||||
"query": "SELECT priv_key_pem, certificate_pem FROM certificates WHERE id = 1;",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -367,27 +366,37 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT priv_key_pem, certificate_pem FROM certificates WHERE id = 1;"
|
||||||
|
},
|
||||||
"7d548d2472fa3707bd17364b4800e229b9c2b1c0a22e245bf4e635b9b16b8c24": {
|
"7d548d2472fa3707bd17364b4800e229b9c2b1c0a22e245bf4e635b9b16b8c24": {
|
||||||
"query": "INSERT INTO certificates (priv_key_pem, certificate_pem, lookup_string, created_at, updated_at) VALUES (?, ?, ?, datetime('now'), datetime('now'))",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 3
|
"Right": 3
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT INTO certificates (priv_key_pem, certificate_pem, lookup_string, created_at, updated_at) VALUES (?, ?, ?, datetime('now'), datetime('now'))"
|
||||||
|
},
|
||||||
|
"82a8fa7eae8a73b5345015c72af024b4f21489b1d9b42235398d7eb8977fb132": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "UPDATE account SET password = ?"
|
||||||
|
},
|
||||||
"8595651866e7db772260bd79e19d55b7271fd795b82a99821c935a9237c1aa16": {
|
"8595651866e7db772260bd79e19d55b7271fd795b82a99821c935a9237c1aa16": {
|
||||||
"query": "SELECT interface, key FROM tor WHERE package = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -401,17 +410,17 @@
|
|||||||
"type_info": "Blob"
|
"type_info": "Blob"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT interface, key FROM tor WHERE package = ?"
|
||||||
|
},
|
||||||
"9496e17a73672ac3675e02efa7c4bf8bd479b866c0d31fa1e3a85ef159310a57": {
|
"9496e17a73672ac3675e02efa7c4bf8bd479b866c0d31fa1e3a85ef159310a57": {
|
||||||
"query": "SELECT priv_key_pem, certificate_pem FROM certificates WHERE lookup_string = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -425,47 +434,47 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT priv_key_pem, certificate_pem FROM certificates WHERE lookup_string = ?"
|
||||||
|
},
|
||||||
"9fcedab1ba34daa2c6ae97c5953c09821b35b55be75b0c66045ab31a2cf4553e": {
|
"9fcedab1ba34daa2c6ae97c5953c09821b35b55be75b0c66045ab31a2cf4553e": {
|
||||||
"query": "REPLACE INTO account (id, password, tor_key) VALUES (?, ?, ?)",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 3
|
"Right": 3
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "REPLACE INTO account (id, password, tor_key) VALUES (?, ?, ?)"
|
||||||
|
},
|
||||||
"a1cbaac36d8e14c8c3e7276237c4824bff18861f91b0b08aa5791704c492acb7": {
|
"a1cbaac36d8e14c8c3e7276237c4824bff18861f91b0b08aa5791704c492acb7": {
|
||||||
"query": "INSERT INTO certificates (id, priv_key_pem, certificate_pem, lookup_string, created_at, updated_at) VALUES (1, ?, ?, NULL, datetime('now'), datetime('now'))",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 2
|
"Right": 2
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT INTO certificates (id, priv_key_pem, certificate_pem, lookup_string, created_at, updated_at) VALUES (1, ?, ?, NULL, datetime('now'), datetime('now'))"
|
||||||
|
},
|
||||||
"a4e7162322b28508310b9de7ebc891e619b881ff6d3ea09eba13da39626ab12f": {
|
"a4e7162322b28508310b9de7ebc891e619b881ff6d3ea09eba13da39626ab12f": {
|
||||||
"query": "UPDATE cifs_shares SET hostname = ?, path = ?, username = ?, password = ? WHERE id = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 5
|
"Right": 5
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "UPDATE cifs_shares SET hostname = ?, path = ?, username = ?, password = ? WHERE id = ?"
|
||||||
|
},
|
||||||
"a6b0c8909a3a5d6d9156aebfb359424e6b5a1d1402e028219e21726f1ebd282e": {
|
"a6b0c8909a3a5d6d9156aebfb359424e6b5a1d1402e028219e21726f1ebd282e": {
|
||||||
"query": "SELECT fingerprint, openssh_pubkey, created_at FROM ssh_keys",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -484,18 +493,18 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT fingerprint, openssh_pubkey, created_at FROM ssh_keys"
|
||||||
|
},
|
||||||
"abfdeea8cd10343b85f647d7abc5dc3bd0b5891101b143485938192ee3b8c907": {
|
"abfdeea8cd10343b85f647d7abc5dc3bd0b5891101b143485938192ee3b8c907": {
|
||||||
"query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications ORDER BY id DESC LIMIT ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -539,9 +548,6 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
@@ -551,21 +557,24 @@
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications ORDER BY id DESC LIMIT ?"
|
||||||
|
},
|
||||||
"b376d9e77e0861a9af2d1081ca48d14e83abc5a1546213d15bb570972c403beb": {
|
"b376d9e77e0861a9af2d1081ca48d14e83abc5a1546213d15bb570972c403beb": {
|
||||||
"query": "-- Add migration script here\nCREATE TABLE IF NOT EXISTS tor\n(\n package TEXT NOT NULL,\n interface TEXT NOT NULL,\n key BLOB NOT NULL CHECK (length(key) = 64),\n PRIMARY KEY (package, interface)\n);\nCREATE TABLE IF NOT EXISTS session\n(\n id TEXT NOT NULL PRIMARY KEY,\n logged_in TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n logged_out TIMESTAMP,\n last_active TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n user_agent TEXT,\n metadata TEXT NOT NULL DEFAULT 'null'\n);\nCREATE TABLE IF NOT EXISTS account\n(\n id INTEGER PRIMARY KEY CHECK (id = 0),\n password TEXT NOT NULL,\n tor_key BLOB NOT NULL CHECK (length(tor_key) = 64)\n);\nCREATE TABLE IF NOT EXISTS ssh_keys\n(\n fingerprint TEXT NOT NULL,\n openssh_pubkey TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (fingerprint)\n);\nCREATE TABLE IF NOT EXISTS certificates\n(\n id INTEGER PRIMARY KEY, -- Root = 0, Int = 1, Other = 2..\n priv_key_pem TEXT NOT NULL,\n certificate_pem TEXT NOT NULL,\n lookup_string TEXT UNIQUE,\n created_at TEXT,\n updated_at TEXT\n);\nCREATE TABLE IF NOT EXISTS notifications\n(\n id INTEGER PRIMARY KEY,\n package_id TEXT,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n code INTEGER NOT NULL,\n level TEXT NOT NULL,\n title TEXT NOT NULL,\n message TEXT NOT NULL,\n data TEXT\n);\nCREATE TABLE IF NOT EXISTS cifs_shares\n(\n id INTEGER PRIMARY KEY,\n hostname TEXT NOT NULL,\n path TEXT NOT NULL,\n username TEXT NOT NULL,\n password TEXT\n);",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 0
|
"Right": 0
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "-- Add migration script here\nCREATE TABLE IF NOT EXISTS tor\n(\n package TEXT NOT NULL,\n interface TEXT NOT NULL,\n key BLOB NOT NULL CHECK (length(key) = 64),\n PRIMARY KEY (package, interface)\n);\nCREATE TABLE IF NOT EXISTS session\n(\n id TEXT NOT NULL PRIMARY KEY,\n logged_in TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n logged_out TIMESTAMP,\n last_active TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n user_agent TEXT,\n metadata TEXT NOT NULL DEFAULT 'null'\n);\nCREATE TABLE IF NOT EXISTS account\n(\n id INTEGER PRIMARY KEY CHECK (id = 0),\n password TEXT NOT NULL,\n tor_key BLOB NOT NULL CHECK (length(tor_key) = 64)\n);\nCREATE TABLE IF NOT EXISTS ssh_keys\n(\n fingerprint TEXT NOT NULL,\n openssh_pubkey TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (fingerprint)\n);\nCREATE TABLE IF NOT EXISTS certificates\n(\n id INTEGER PRIMARY KEY, -- Root = 0, Int = 1, Other = 2..\n priv_key_pem TEXT NOT NULL,\n certificate_pem TEXT NOT NULL,\n lookup_string TEXT UNIQUE,\n created_at TEXT,\n updated_at TEXT\n);\nCREATE TABLE IF NOT EXISTS notifications\n(\n id INTEGER PRIMARY KEY,\n package_id TEXT,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n code INTEGER NOT NULL,\n level TEXT NOT NULL,\n title TEXT NOT NULL,\n message TEXT NOT NULL,\n data TEXT\n);\nCREATE TABLE IF NOT EXISTS cifs_shares\n(\n id INTEGER PRIMARY KEY,\n hostname TEXT NOT NULL,\n path TEXT NOT NULL,\n username TEXT NOT NULL,\n password TEXT\n);"
|
||||||
|
},
|
||||||
"cc33fe2958fe7caeac6999a217f918a68b45ad596664170b4d07671c6ea49566": {
|
"cc33fe2958fe7caeac6999a217f918a68b45ad596664170b4d07671c6ea49566": {
|
||||||
"query": "SELECT hostname, path, username, password FROM cifs_shares WHERE id = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -589,19 +598,19 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT hostname, path, username, password FROM cifs_shares WHERE id = ?"
|
||||||
|
},
|
||||||
"d5117054072476377f3c4f040ea429d4c9b2cf534e76f35c80a2bf60e8599cca": {
|
"d5117054072476377f3c4f040ea429d4c9b2cf534e76f35c80a2bf60e8599cca": {
|
||||||
"query": "SELECT openssh_pubkey FROM ssh_keys",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -610,36 +619,36 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT openssh_pubkey FROM ssh_keys"
|
||||||
|
},
|
||||||
"d54bd5b53f8c760e1f8cde604aa8b1bdc66e4e025a636bc44ffbcd788b5168fd": {
|
"d54bd5b53f8c760e1f8cde604aa8b1bdc66e4e025a636bc44ffbcd788b5168fd": {
|
||||||
"query": "INSERT INTO notifications (package_id, code, level, title, message, data) VALUES (?, ?, ?, ?, ?, ?)",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 6
|
"Right": 6
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT INTO notifications (package_id, code, level, title, message, data) VALUES (?, ?, ?, ?, ?, ?)"
|
||||||
|
},
|
||||||
"d79d608ceb862c15b741a6040044c6dd54a837a3a0c5594d15a6041c7bc68ea8": {
|
"d79d608ceb862c15b741a6040044c6dd54a837a3a0c5594d15a6041c7bc68ea8": {
|
||||||
"query": "INSERT OR IGNORE INTO tor (package, interface, key) VALUES (?, ?, ?)",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 3
|
"Right": 3
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "INSERT OR IGNORE INTO tor (package, interface, key) VALUES (?, ?, ?)"
|
||||||
|
},
|
||||||
"de2a5e90798d606047ab8180c044baac05469c0cdf151316bd58ee8c7196fdef": {
|
"de2a5e90798d606047ab8180c044baac05469c0cdf151316bd58ee8c7196fdef": {
|
||||||
"query": "SELECT * FROM ssh_keys WHERE fingerprint = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -658,18 +667,18 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 1
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT * FROM ssh_keys WHERE fingerprint = ?"
|
||||||
|
},
|
||||||
"ed848affa5bf92997cd441e3a50b3616b6724df3884bd9d199b3225e0bea8a54": {
|
"ed848affa5bf92997cd441e3a50b3616b6724df3884bd9d199b3225e0bea8a54": {
|
||||||
"query": "SELECT priv_key_pem, certificate_pem FROM certificates WHERE id = 0;",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -683,23 +692,24 @@
|
|||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
|
||||||
"Right": 0
|
|
||||||
},
|
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
]
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"query": "SELECT priv_key_pem, certificate_pem FROM certificates WHERE id = 0;"
|
||||||
|
},
|
||||||
"f63c8c5a8754b34a49ef5d67802fa2b72aa409bbec92ecc6901492092974b71a": {
|
"f63c8c5a8754b34a49ef5d67802fa2b72aa409bbec92ecc6901492092974b71a": {
|
||||||
"query": "DELETE FROM cifs_shares WHERE id = ?",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 1
|
"Right": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"nullable": []
|
"query": "DELETE FROM cifs_shares WHERE id = ?"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ use std::marker::PhantomData;
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use color_eyre::eyre::eyre;
|
use color_eyre::eyre::eyre;
|
||||||
|
use patch_db::{DbHandle, LockReceipt};
|
||||||
use rpc_toolkit::command;
|
use rpc_toolkit::command;
|
||||||
use rpc_toolkit::command_helpers::prelude::{RequestParts, ResponseParts};
|
use rpc_toolkit::command_helpers::prelude::{RequestParts, ResponseParts};
|
||||||
use rpc_toolkit::yajrc::RpcError;
|
use rpc_toolkit::yajrc::RpcError;
|
||||||
@@ -18,7 +19,7 @@ use crate::util::display_none;
|
|||||||
use crate::util::serde::{display_serializable, IoFormat};
|
use crate::util::serde::{display_serializable, IoFormat};
|
||||||
use crate::{ensure_code, Error, ResultExt};
|
use crate::{ensure_code, Error, ResultExt};
|
||||||
|
|
||||||
#[command(subcommands(login, logout, session))]
|
#[command(subcommands(login, logout, session, reset_password))]
|
||||||
pub fn auth() -> Result<(), Error> {
|
pub fn auth() -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -256,3 +257,113 @@ pub async fn kill(
|
|||||||
HasLoggedOutSessions::new(ids.into_iter().map(KillSessionId), &ctx).await?;
|
HasLoggedOutSessions::new(ids.into_iter().map(KillSessionId), &ctx).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(ctx, old_password, new_password))]
|
||||||
|
async fn cli_reset_password(
|
||||||
|
ctx: CliContext,
|
||||||
|
old_password: Option<String>,
|
||||||
|
new_password: Option<String>,
|
||||||
|
) -> Result<(), RpcError> {
|
||||||
|
let old_password = if let Some(old_password) = old_password {
|
||||||
|
old_password
|
||||||
|
} else {
|
||||||
|
rpassword::prompt_password_stdout("Current Password: ")?
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_password = if let Some(new_password) = new_password {
|
||||||
|
new_password
|
||||||
|
} else {
|
||||||
|
let new_password = rpassword::prompt_password_stdout("New Password: ")?;
|
||||||
|
if new_password != rpassword::prompt_password_stdout("Confirm: ")? {
|
||||||
|
return Err(Error::new(
|
||||||
|
eyre!("Passwords do not match"),
|
||||||
|
crate::ErrorKind::IncorrectPassword,
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
new_password
|
||||||
|
};
|
||||||
|
|
||||||
|
rpc_toolkit::command_helpers::call_remote(
|
||||||
|
ctx,
|
||||||
|
"auth.reset-password",
|
||||||
|
serde_json::json!({ "old-password": old_password, "new-password": new_password }),
|
||||||
|
PhantomData::<()>,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.result?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SetPasswordReceipt(LockReceipt<String, ()>);
|
||||||
|
impl SetPasswordReceipt {
|
||||||
|
pub async fn new<Db: DbHandle>(db: &mut Db) -> Result<Self, Error> {
|
||||||
|
let mut locks = Vec::new();
|
||||||
|
|
||||||
|
let setup = Self::setup(&mut locks);
|
||||||
|
Ok(setup(&db.lock_all(locks).await?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(
|
||||||
|
locks: &mut Vec<patch_db::LockTargetId>,
|
||||||
|
) -> impl FnOnce(&patch_db::Verifier) -> Result<Self, Error> {
|
||||||
|
let password_hash = crate::db::DatabaseModel::new()
|
||||||
|
.server_info()
|
||||||
|
.password_hash()
|
||||||
|
.make_locker(patch_db::LockType::Write)
|
||||||
|
.add_to_keys(locks);
|
||||||
|
move |skeleton_key| Ok(Self(password_hash.verify(skeleton_key)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_password<Db: DbHandle, Ex>(
|
||||||
|
db: &mut Db,
|
||||||
|
receipt: &SetPasswordReceipt,
|
||||||
|
secrets: &mut Ex,
|
||||||
|
password: &str,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
|
||||||
|
{
|
||||||
|
let password = argon2::hash_encoded(
|
||||||
|
password.as_bytes(),
|
||||||
|
&rand::random::<[u8; 16]>()[..],
|
||||||
|
&argon2::Config::default(),
|
||||||
|
)
|
||||||
|
.with_kind(crate::ErrorKind::PasswordHashGeneration)?;
|
||||||
|
|
||||||
|
sqlx::query!("UPDATE account SET password = ?", password,)
|
||||||
|
.execute(secrets)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
receipt.0.set(db, password).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command(
|
||||||
|
rename = "reset-password",
|
||||||
|
custom_cli(cli_reset_password(async, context(CliContext))),
|
||||||
|
display(display_none)
|
||||||
|
)]
|
||||||
|
#[instrument(skip(ctx, old_password, new_password))]
|
||||||
|
pub async fn reset_password(
|
||||||
|
#[context] ctx: RpcContext,
|
||||||
|
#[arg(rename = "old-password")] old_password: Option<String>,
|
||||||
|
#[arg(rename = "new-password")] new_password: Option<String>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let old_password = old_password.unwrap_or_default();
|
||||||
|
let new_password = new_password.unwrap_or_default();
|
||||||
|
|
||||||
|
let mut secrets = ctx.secret_store.acquire().await?;
|
||||||
|
check_password_against_db(&mut secrets, &old_password).await?;
|
||||||
|
|
||||||
|
let mut db = ctx.db.handle();
|
||||||
|
|
||||||
|
let set_password_receipt = SetPasswordReceipt::new(&mut db).await?;
|
||||||
|
|
||||||
|
set_password(&mut db, &set_password_receipt, &mut secrets, &new_password).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub struct StartReceipts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StartReceipts {
|
impl StartReceipts {
|
||||||
pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result<Self, Error> {
|
pub async fn new(db: &mut impl DbHandle, id: &PackageId) -> Result<Self, Error> {
|
||||||
let mut locks = Vec::new();
|
let mut locks = Vec::new();
|
||||||
|
|
||||||
let setup = Self::setup(&mut locks, id);
|
let setup = Self::setup(&mut locks, id);
|
||||||
|
|||||||
@@ -34,33 +34,21 @@ impl HasLoggedOutSessions {
|
|||||||
logged_out_sessions: impl IntoIterator<Item = impl AsLogoutSessionId>,
|
logged_out_sessions: impl IntoIterator<Item = impl AsLogoutSessionId>,
|
||||||
ctx: &RpcContext,
|
ctx: &RpcContext,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let sessions = logged_out_sessions
|
let mut open_authed_websockets = ctx.open_authed_websockets.lock().await;
|
||||||
.into_iter()
|
|
||||||
.by_ref()
|
|
||||||
.map(|x| x.as_logout_session_id())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let mut sqlx_conn = ctx.secret_store.acquire().await?;
|
let mut sqlx_conn = ctx.secret_store.acquire().await?;
|
||||||
for session in &sessions {
|
for session in logged_out_sessions {
|
||||||
|
let session = session.as_logout_session_id();
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = ?",
|
"UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = ?",
|
||||||
session
|
session
|
||||||
)
|
)
|
||||||
.execute(&mut sqlx_conn)
|
.execute(&mut sqlx_conn)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
for socket in open_authed_websockets.remove(&session).unwrap_or_default() {
|
||||||
drop(sqlx_conn);
|
|
||||||
for session in sessions {
|
|
||||||
for socket in ctx
|
|
||||||
.open_authed_websockets
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.remove(&session)
|
|
||||||
.unwrap_or_default()
|
|
||||||
{
|
|
||||||
let _ = socket.send(());
|
let _ = socket.send(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Self(()))
|
Ok(HasLoggedOutSessions(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ use futures::future::BoxFuture;
|
|||||||
use futures::{FutureExt, TryFutureExt, TryStreamExt};
|
use futures::{FutureExt, TryFutureExt, TryStreamExt};
|
||||||
use nix::unistd::{Gid, Uid};
|
use nix::unistd::{Gid, Uid};
|
||||||
use openssl::x509::X509;
|
use openssl::x509::X509;
|
||||||
use patch_db::LockType;
|
use patch_db::{DbHandle, LockType};
|
||||||
use rpc_toolkit::command;
|
use rpc_toolkit::command;
|
||||||
use rpc_toolkit::yajrc::RpcError;
|
use rpc_toolkit::yajrc::RpcError;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use sqlx::{Executor, Sqlite};
|
use sqlx::{Connection, Executor, Sqlite};
|
||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use torut::onion::{OnionAddressV3, TorSecretKeyV3};
|
use torut::onion::{OnionAddressV3, TorSecretKeyV3};
|
||||||
@@ -96,6 +96,7 @@ pub async fn list_disks() -> Result<DiskListResponse, Error> {
|
|||||||
pub async fn attach(
|
pub async fn attach(
|
||||||
#[context] ctx: SetupContext,
|
#[context] ctx: SetupContext,
|
||||||
#[arg] guid: Arc<String>,
|
#[arg] guid: Arc<String>,
|
||||||
|
#[arg(rename = "embassy-password")] password: Option<String>,
|
||||||
) -> Result<SetupResult, Error> {
|
) -> Result<SetupResult, Error> {
|
||||||
let requires_reboot = crate::disk::main::import(
|
let requires_reboot = crate::disk::main::import(
|
||||||
&*guid,
|
&*guid,
|
||||||
@@ -148,7 +149,28 @@ pub async fn attach(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let secrets = ctx.secret_store().await?;
|
let secrets = ctx.secret_store().await?;
|
||||||
let tor_key = crate::net::tor::os_key(&mut secrets.acquire().await?).await?;
|
let db = ctx.db(&secrets).await?;
|
||||||
|
let mut secrets_handle = secrets.acquire().await?;
|
||||||
|
let mut db_handle = db.handle();
|
||||||
|
let mut secrets_tx = secrets_handle.begin().await?;
|
||||||
|
let mut db_tx = db_handle.begin().await?;
|
||||||
|
|
||||||
|
if let Some(password) = password {
|
||||||
|
let set_password_receipt = crate::auth::SetPasswordReceipt::new(&mut db_tx).await?;
|
||||||
|
crate::auth::set_password(
|
||||||
|
&mut db_tx,
|
||||||
|
&set_password_receipt,
|
||||||
|
&mut secrets_tx,
|
||||||
|
&password,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tor_key = crate::net::tor::os_key(&mut secrets_tx).await?;
|
||||||
|
|
||||||
|
db_tx.commit(None).await?;
|
||||||
|
secrets_tx.commit().await?;
|
||||||
|
|
||||||
let (_, root_ca) = SslManager::init(secrets).await?.export_root_ca().await?;
|
let (_, root_ca) = SslManager::init(secrets).await?.export_root_ca().await?;
|
||||||
let setup_result = SetupResult {
|
let setup_result = SetupResult {
|
||||||
tor_address: format!("http://{}", tor_key.public().get_onion_address()),
|
tor_address: format!("http://{}", tor_key.public().get_onion_address()),
|
||||||
|
|||||||
@@ -99,8 +99,7 @@ export class RecoverPage {
|
|||||||
const alert = await this.alertCtrl.create({
|
const alert = await this.alertCtrl.create({
|
||||||
header: 'Embassy Data Drive Detected',
|
header: 'Embassy Data Drive Detected',
|
||||||
message: new IonicSafeString(
|
message: new IonicSafeString(
|
||||||
`${importableDrive.vendor || 'Unknown Vendor'} - ${
|
`${importableDrive.vendor || 'Unknown Vendor'} - ${importableDrive.model || 'Unknown Model'
|
||||||
importableDrive.model || 'Unknown Model'
|
|
||||||
} contains Embassy data. To use this drive and its data <i>as-is</i>, click "Use Drive". This will complete the setup process.<br /><br /><b>Important</b>. If you are trying to restore from backup or update from 0.2.x, DO NOT click "Use Drive". Instead, click "Cancel" and follow instructions.`,
|
} contains Embassy data. To use this drive and its data <i>as-is</i>, click "Use Drive". This will complete the setup process.<br /><br /><b>Important</b>. If you are trying to restore from backup or update from 0.2.x, DO NOT click "Use Drive". Instead, click "Cancel" and follow instructions.`,
|
||||||
),
|
),
|
||||||
buttons: [
|
buttons: [
|
||||||
@@ -111,8 +110,16 @@ export class RecoverPage {
|
|||||||
{
|
{
|
||||||
text: 'Use Drive',
|
text: 'Use Drive',
|
||||||
handler: async () => {
|
handler: async () => {
|
||||||
if (importableDrive.guid)
|
const modal = await this.modalController.create({
|
||||||
await this.importDrive(importableDrive.guid)
|
component: PasswordPage,
|
||||||
|
componentProps: { storageDrive: importableDrive },
|
||||||
|
})
|
||||||
|
modal.onDidDismiss().then(res => {
|
||||||
|
if (res.data && res.data.password) {
|
||||||
|
this.importDrive(importableDrive.guid!, res.data.password)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await modal.present()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -201,13 +208,13 @@ export class RecoverPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async importDrive(guid: string) {
|
private async importDrive(guid: string, password: string) {
|
||||||
const loader = await this.loadingCtrl.create({
|
const loader = await this.loadingCtrl.create({
|
||||||
message: 'Importing Drive',
|
message: 'Importing Drive',
|
||||||
})
|
})
|
||||||
await loader.present()
|
await loader.present()
|
||||||
try {
|
try {
|
||||||
await this.stateService.importDrive(guid)
|
await this.stateService.importDrive(guid, password)
|
||||||
await this.navCtrl.navigateForward(`/success`)
|
await this.navCtrl.navigateForward(`/success`)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.errorToastService.present(e)
|
this.errorToastService.present(e)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export abstract class ApiService {
|
|||||||
// encrypted
|
// encrypted
|
||||||
abstract verifyCifs(cifs: CifsRecoverySource): Promise<EmbassyOSRecoveryInfo> // setup.cifs.verify
|
abstract verifyCifs(cifs: CifsRecoverySource): Promise<EmbassyOSRecoveryInfo> // setup.cifs.verify
|
||||||
abstract verifyProductKey(): Promise<void> // echo - throws error if invalid
|
abstract verifyProductKey(): Promise<void> // echo - throws error if invalid
|
||||||
abstract importDrive(guid: string): Promise<SetupEmbassyRes> // setup.execute
|
abstract importDrive(importInfo: ImportDriveReq): Promise<SetupEmbassyRes> // setup.attach
|
||||||
abstract setupEmbassy(setupInfo: SetupEmbassyReq): Promise<SetupEmbassyRes> // setup.execute
|
abstract setupEmbassy(setupInfo: SetupEmbassyReq): Promise<SetupEmbassyRes> // setup.execute
|
||||||
abstract setupComplete(): Promise<SetupEmbassyRes> // setup.complete
|
abstract setupComplete(): Promise<SetupEmbassyRes> // setup.complete
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,11 @@ export interface GetStatusRes {
|
|||||||
migrating: boolean
|
migrating: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ImportDriveReq {
|
||||||
|
guid: string
|
||||||
|
'embassy-password': string
|
||||||
|
}
|
||||||
|
|
||||||
export interface SetupEmbassyReq {
|
export interface SetupEmbassyReq {
|
||||||
'embassy-logicalname': string
|
'embassy-logicalname': string
|
||||||
'embassy-password': string
|
'embassy-password': string
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { Injectable } from '@angular/core'
|
|||||||
import {
|
import {
|
||||||
ApiService,
|
ApiService,
|
||||||
CifsRecoverySource,
|
CifsRecoverySource,
|
||||||
DiskInfo,
|
|
||||||
DiskListResponse,
|
DiskListResponse,
|
||||||
DiskRecoverySource,
|
DiskRecoverySource,
|
||||||
EmbassyOSRecoveryInfo,
|
EmbassyOSRecoveryInfo,
|
||||||
GetStatusRes,
|
GetStatusRes,
|
||||||
|
ImportDriveReq,
|
||||||
RecoveryStatusRes,
|
RecoveryStatusRes,
|
||||||
SetupEmbassyReq,
|
SetupEmbassyReq,
|
||||||
SetupEmbassyRes,
|
SetupEmbassyRes,
|
||||||
@@ -80,10 +80,10 @@ export class LiveApiService extends ApiService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async importDrive(guid: string) {
|
async importDrive(params: ImportDriveReq) {
|
||||||
const res = await this.http.rpcRequest<SetupEmbassyRes>({
|
const res = await this.http.rpcRequest<SetupEmbassyRes>({
|
||||||
method: 'setup.attach',
|
method: 'setup.attach',
|
||||||
params: { guid },
|
params: params as any,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { pauseFor } from '@start9labs/shared'
|
import { pauseFor } from '@start9labs/shared'
|
||||||
import { ApiService, CifsRecoverySource, SetupEmbassyReq } from './api.service'
|
import {
|
||||||
|
ApiService,
|
||||||
|
CifsRecoverySource,
|
||||||
|
ImportDriveReq,
|
||||||
|
SetupEmbassyReq,
|
||||||
|
} from './api.service'
|
||||||
|
|
||||||
let tries = 0
|
let tries = 0
|
||||||
|
|
||||||
@@ -84,7 +89,7 @@ export class MockApiService extends ApiService {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
async importDrive(guid: string) {
|
async importDrive(params: ImportDriveReq) {
|
||||||
await pauseFor(3000)
|
await pauseFor(3000)
|
||||||
return setupRes
|
return setupRes
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,8 +69,11 @@ export class StateService {
|
|||||||
setTimeout(() => this.pollDataTransferProgress(), 0) // prevent call stack from growing
|
setTimeout(() => this.pollDataTransferProgress(), 0) // prevent call stack from growing
|
||||||
}
|
}
|
||||||
|
|
||||||
async importDrive(guid: string): Promise<void> {
|
async importDrive(guid: string, password: string): Promise<void> {
|
||||||
const ret = await this.apiService.importDrive(guid)
|
const ret = await this.apiService.importDrive({
|
||||||
|
guid,
|
||||||
|
'embassy-password': password,
|
||||||
|
})
|
||||||
this.torAddress = ret['tor-address']
|
this.torAddress = ret['tor-address']
|
||||||
this.lanAddress = ret['lan-address']
|
this.lanAddress = ret['lan-address']
|
||||||
this.cert = ret['root-ca']
|
this.cert = ret['root-ca']
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export class LoginPage {
|
|||||||
.setVerified()
|
.setVerified()
|
||||||
.then(() => this.router.navigate([''], { replaceUrl: true }))
|
.then(() => this.router.navigate([''], { replaceUrl: true }))
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.error = e.code === 34 ? 'Invalid Password' : e.message
|
// code 7 is for incorrect password
|
||||||
|
this.error = e.code === 7 ? 'Invalid Password' : e.message
|
||||||
} finally {
|
} finally {
|
||||||
this.loader.dismiss()
|
this.loader.dismiss()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export class HttpService {
|
|||||||
|
|
||||||
const res = await this.httpRequest<RPCResponse<T>>(httpOpts)
|
const res = await this.httpRequest<RPCResponse<T>>(httpOpts)
|
||||||
if (isRpcError(res)) {
|
if (isRpcError(res)) {
|
||||||
|
// code 34 is authorization error ie. invalid session
|
||||||
if (res.error.code === 34) this.auth.setUnverified()
|
if (res.error.code === 34) this.auth.setUnverified()
|
||||||
throw new RpcError(res.error)
|
throw new RpcError(res.error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use deno_core::anyhow::{anyhow, bail};
|
use deno_core::anyhow::{anyhow, bail};
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::{
|
use deno_core::{
|
||||||
@@ -11,7 +13,6 @@ use helpers::{script_dir, NonDetachingJoinHandle};
|
|||||||
use models::{PackageId, ProcedureName, Version, VolumeId};
|
use models::{PackageId, ProcedureName, Version, VolumeId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::time::SystemTime;
|
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
pub trait PathForVolumeId: Send + Sync {
|
pub trait PathForVolumeId: Send + Sync {
|
||||||
@@ -331,18 +332,18 @@ impl JsExecutionEnvironment {
|
|||||||
mod fns {
|
mod fns {
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::os::unix::fs::MetadataExt;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use deno_core::anyhow::{anyhow, bail};
|
use deno_core::anyhow::{anyhow, bail};
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::*;
|
use deno_core::*;
|
||||||
use models::VolumeId;
|
use models::VolumeId;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::os::unix::fs::MetadataExt;
|
|
||||||
|
|
||||||
use crate::{system_time_as_unix_ms, MetadataJs};
|
|
||||||
|
|
||||||
use super::{AnswerState, JsContext};
|
use super::{AnswerState, JsContext};
|
||||||
|
use crate::{system_time_as_unix_ms, MetadataJs};
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
async fn read_file(
|
async fn read_file(
|
||||||
|
|||||||
Reference in New Issue
Block a user