mirror of
https://github.com/Skylar-Tech/node-red-contrib-matrix-chat.git
synced 2025-04-20 13:03:12 -06:00
WIP on secret storage node
This commit is contained in:
parent
36c8208b01
commit
678702e9c6
@ -33,7 +33,8 @@
|
|||||||
"matrix-synapse-join-room": "src/matrix-synapse-join-room.js",
|
"matrix-synapse-join-room": "src/matrix-synapse-join-room.js",
|
||||||
"matrix-whois-user": "src/matrix-whois-user.js",
|
"matrix-whois-user": "src/matrix-whois-user.js",
|
||||||
"matrix-room-users": "src/matrix-room-users.js",
|
"matrix-room-users": "src/matrix-room-users.js",
|
||||||
"matrix-device-verify": "src/matrix-device-verify.js"
|
"matrix-device-verify": "src/matrix-device-verify.js",
|
||||||
|
"matrix-secret-storage": "src/matrix-secret-storage.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -39,13 +39,14 @@ module.exports = function(RED) {
|
|||||||
* rejected.
|
* rejected.
|
||||||
*/
|
*/
|
||||||
node.server.matrixClient.on("crypto.verification.request", async function(data){
|
node.server.matrixClient.on("crypto.verification.request", async function(data){
|
||||||
console.log("[######### crypto.verification.request #########]");
|
console.log("[######### crypto.verification.request #########]", data.phase, data.methods);
|
||||||
if(data.isSelfVerification) {
|
if(data.isSelfVerification) {
|
||||||
if(data.requested && data.methods) {
|
if(data.requested || true) {
|
||||||
let verifyRequestId = data.targetDevice.userId + ':' + data.targetDevice.deviceId;
|
let verifyRequestId = data.targetDevice.userId + ':' + data.targetDevice.deviceId;
|
||||||
verificationRequests.set(verifyRequestId, data);
|
verificationRequests.set(verifyRequestId, data);
|
||||||
node.send({
|
node.send({
|
||||||
verifyRequestId: verifyRequestId, // internally used to reference between nodes
|
verifyRequestId: verifyRequestId, // internally used to reference between nodesc
|
||||||
|
verifyMethods: data.methods,
|
||||||
userId: data.targetDevice.userId,
|
userId: data.targetDevice.userId,
|
||||||
deviceId: data.targetDevice.deviceId,
|
deviceId: data.targetDevice.deviceId,
|
||||||
type: 'crypto.verification.request',
|
type: 'crypto.verification.request',
|
||||||
@ -139,6 +140,7 @@ module.exports = function(RED) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
data._verifier.on('cancel', function(e){
|
data._verifier.on('cancel', function(e){
|
||||||
|
node.warn("Device verificaiton cancelled " + e);
|
||||||
verifierCancel();
|
verifierCancel();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -180,6 +182,8 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
data.emit("change");
|
||||||
|
|
||||||
await data.accept();
|
await data.accept();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log("ERROR", e);
|
console.log("ERROR", e);
|
||||||
|
71
src/matrix-secret-storage.html
Normal file
71
src/matrix-secret-storage.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('matrix-secret-storage', {
|
||||||
|
category: 'matrix',
|
||||||
|
color: '#00b7ca',
|
||||||
|
icon: "matrix.png",
|
||||||
|
inputs: 1,
|
||||||
|
outputs: 1,
|
||||||
|
defaults: {
|
||||||
|
name: { value: null },
|
||||||
|
server: { value: "", type: "matrix-server-config" }
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.name || "Secret Storage";
|
||||||
|
},
|
||||||
|
paletteLabel: 'Secret Storage'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-template-name="matrix-secret-storage">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-server"><i class="fa fa-user"></i> Matrix Server Config</label>
|
||||||
|
<input type="text" id="node-input-server">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" data-help-name="matrix-secret-storage">
|
||||||
|
<h3>Details</h3>
|
||||||
|
<p>
|
||||||
|
Secure backup node. Use this to setup security key backup to the remote server. You can also use this node to import an existing secure backup.
|
||||||
|
</p>
|
||||||
|
<a href="https://matrix-org.github.io/synapse/develop/admin_api/room_membership.html#edit-room-membership-api" target="_blank">Synapse API Endpoint Information</a>
|
||||||
|
|
||||||
|
<h3>Inputs</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.topic
|
||||||
|
<span class="property-type">string</span>
|
||||||
|
</dt>
|
||||||
|
<dd> The room identifier to invite to: for example, <code>!h8zld9j31:example.com. If configured on the node it overrides this input and is no longer required.</code>.</dd>
|
||||||
|
|
||||||
|
<dt>msg.userId
|
||||||
|
<span class="property-type">string</span>
|
||||||
|
</dt>
|
||||||
|
<dd> User's ID that will be invited to the room.</dd>
|
||||||
|
|
||||||
|
<dt class="optional">msg.reason
|
||||||
|
<span class="property-type">string</span>
|
||||||
|
</dt>
|
||||||
|
<dd> Reason for the membership change.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3>Outputs</h3>
|
||||||
|
<ol class="node-ports">
|
||||||
|
<li>Success
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.payload <span class="property-type">object</span></dt>
|
||||||
|
<dd>Currently this endpoint returns an empty object</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li>Error
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>msg.error <span class="property-type">string</span></dt>
|
||||||
|
<dd>the error that occurred.</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</script>
|
92
src/matrix-secret-storage.js
Normal file
92
src/matrix-secret-storage.js
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
module.exports = function(RED) {
|
||||||
|
const verificationRequests = new Map();
|
||||||
|
|
||||||
|
function MatrixSecretStorage(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
this.name = n.name;
|
||||||
|
this.server = RED.nodes.getNode(n.server);
|
||||||
|
|
||||||
|
if (!node.server) {
|
||||||
|
node.warn("No configuration node");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
|
||||||
|
node.server.on("disconnected", function(){
|
||||||
|
node.status({ fill: "red", shape: "ring", text: "disconnected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.server.on("connected", function() {
|
||||||
|
node.status({ fill: "green", shape: "ring", text: "connected" });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on('input', async function(msg){
|
||||||
|
try {
|
||||||
|
msg.hasSecretStorage = await node.server.matrixClient.hasSecretStorageKey();
|
||||||
|
} catch(e) {
|
||||||
|
console.log("ERROR", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg.action) {
|
||||||
|
if(msg.action === 'create') {
|
||||||
|
if(msg.hasSecretStorage && !msg.forceReset) {
|
||||||
|
node.error("Secret storage already setup. Pass msg.forceReset to bypass and regenerate.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// copying this from https://github.com/matrix-org/matrix-react-sdk/blob/e78a1adb6f1af2ea425b0bae9034fb7344a4b2e8/src/SecurityManager.ts#L294
|
||||||
|
const recoveryKey = await node.server.matrixClient.createRecoveryKeyFromPassphrase(msg.key || undefined);
|
||||||
|
if(msg.forceReset) {
|
||||||
|
await node.server.matrixClient.bootstrapSecretStorage({
|
||||||
|
createSecretStorageKey: async () => recoveryKey,
|
||||||
|
setupNewKeyBackup: true,
|
||||||
|
setupNewSecretStorage: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// For password authentication users after 2020-09, this cross-signing
|
||||||
|
// step will be a no-op since it is now setup during registration or login
|
||||||
|
// when needed. We should keep this here to cover other cases such as:
|
||||||
|
// * Users with existing sessions prior to 2020-09 changes
|
||||||
|
// * SSO authentication users which require interactive auth to upload
|
||||||
|
// keys (and also happen to skip all post-authentication flows at the
|
||||||
|
// moment via token login)
|
||||||
|
await node.server.matrixClient.bootstrapCrossSigning({
|
||||||
|
// maybe we can skip this?
|
||||||
|
// authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
|
||||||
|
});
|
||||||
|
const backupState = await node.server.matrixClient.getKeyBackupVersion();
|
||||||
|
await node.server.matrixClient.bootstrapSecretStorage({
|
||||||
|
createSecretStorageKey: async () => this._recoveryKey,
|
||||||
|
keyBackupInfo: backupState.backupInfo,
|
||||||
|
setupNewKeyBackup: !backupState.backupInfo,
|
||||||
|
getKeyBackupPassphrase: () => {
|
||||||
|
// We may already have the backup key if we earlier went
|
||||||
|
// through the restore backup path, so pass it along
|
||||||
|
// rather than prompting again.
|
||||||
|
if (this._backupKey) {
|
||||||
|
return this._backupKey;
|
||||||
|
}
|
||||||
|
return promptForBackupPassphrase();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg.action === 'download') {
|
||||||
|
if(!msg.hasSecretStorage) {
|
||||||
|
node.error("Secret storage not setup so cannot download.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("matrix-secret-storage", MatrixSecretStorage);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user