This repository was archived by the owner on Feb 6, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathrotate-key-pair.js
87 lines (74 loc) · 2.56 KB
/
rotate-key-pair.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { ajax } from "discourse/lib/ajax";
import { extractError } from "discourse/lib/ajax-error";
import { saveDbIdentity } from "discourse/plugins/discourse-encrypt/lib/database";
import { getIdentity } from "discourse/plugins/discourse-encrypt/lib/discourse";
import {
exportIdentity,
exportKey,
generateIdentity,
importKey,
} from "discourse/plugins/discourse-encrypt/lib/protocol";
export default class RotateKeyPair extends Component {
@service currentUser;
@service appEvents;
@tracked confirmation = "";
@tracked loadingState;
@tracked error;
get label() {
return this.loadingState
? `encrypt.rotate.loading_states.${this.loadingState}`
: "encrypt.rotate.title";
}
get disabled() {
return this.loadingState || this.currentUser.username !== this.confirmation;
}
@action
async rotate() {
this.loadingState = "fetching";
this.error = null;
try {
const [data, oldIdentity, newIdentity] = await Promise.all([
ajax("/encrypt/rotate"),
getIdentity(),
generateIdentity(),
]);
this.loadingState = "rotating";
// Don't rotate signatures because that will invalidate all previous
// signatures.
// When the old identity is v0, there's no keypair for signing, so don't
// overwrite the new identity's signing keypair with nothing (undefined)
if (oldIdentity.signPublic && oldIdentity.signPrivate) {
newIdentity.signPublic = oldIdentity.signPublic;
newIdentity.signPrivate = oldIdentity.signPrivate;
}
const topicKeys = {};
await Promise.all(
Object.entries(data.topic_keys).map(async ([topicId, topicKey]) => {
const key = await importKey(topicKey, oldIdentity.encryptPrivate);
topicKeys[topicId] = await exportKey(key, newIdentity.encryptPublic);
})
);
const exportedIdentity = await exportIdentity(newIdentity);
this.loadingState = "saving";
await ajax("/encrypt/rotate", {
type: "PUT",
data: {
public: exportedIdentity.public,
keys: topicKeys,
},
});
this.loadingState = "updating";
await saveDbIdentity(newIdentity);
this.loadingState = "finished";
this.appEvents.trigger("encrypt:status-changed");
} catch (error) {
this.confirmation = "";
this.loadingState = null;
this.error = extractError(error);
}
}
}