-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdisplayotp.js
202 lines (174 loc) · 6.44 KB
/
displayotp.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
function getAlgorithm(n) {
return ["SHA1", "SHA256", "SHA512"][n];
}
// on: name, issuer, created
// order: asc, desc
function sortAccounts(on, order) {
if (order != "asc" && order != "desc") return false;
switch (on) {
case "name":
if (order == "asc") {
window.accounts.sort((a, b) => a.name.localeCompare(b.name))
} else {
window.accounts.sort((a, b) => b.name.localeCompare(a.name))
}
return true;
case "issuer":
if (order == "asc") {
window.accounts.sort((a, b) => a.issuer.localeCompare(b.issuer))
} else {
window.accounts.sort((a, b) => b.issuer.localeCompare(a.issuer))
}
return true;
case "created":
if (order == "asc") {
window.accounts.sort((a, b) => a.created_at.localeCompare(b.created_at))
} else {
window.accounts.sort((a, b) => b.created_at.localeCompare(a.created_at))
}
return true;
default:
if (order == "asc") {
window.accounts.sort((a, b) => a.position - b.position)
} else {
window.accounts.sort((a, b) => b.position - a.position)
}
return true;
}
}
function getOtpFromAccount(account) {
const passHash = CryptoJS.SHA256(window.password).toString()
const key = CryptoJS.enc.Hex.parse(passHash);
const parsedIv = CryptoJS.enc.Hex.parse(window.accountIV);
const dec = CryptoJS.AES.decrypt(account.secret, key, { iv: parsedIv });
const secret = dec.toString(CryptoJS.enc.Utf8);
if (account.type == "totp") {
const totp = new OTPAuth.TOTP({
issuer: account.issuer,
label: account.name,
algorithm: getAlgorithm(account.algorithm),
digits: account.digits,
period: account.period,
secret: secret,
});
return totp.generate();
} else {
if (account.counter == 0) {
account.code = "Click to generate code";
} else {
const hotp = new OTPAuth.HOTP({
issuer: account.issuer,
label: account.name,
algorithm: getAlgorithm(account.algorithm),
digits: account.digits,
counter: account.counter,
secret: secret,
});
return hotp.generate();
}
}
}
function generateAccountSegment(account) {
const template = document.querySelector(account.type === "totp" ? "#totp-template" : "#hotp-template")
const clone = template.content.cloneNode(true)
const icon = account.icon === "default" ? "img/vpn-key.svg" : "https://cdn.simpleicons.org/"+ account.icon
clone.querySelector(".accounticon").src = icon
clone.querySelector(".accountname").textContent = account.name
clone.querySelector(".accountissuer").textContent = account.issuer
const otpValue = getOtpFromAccount(account)
let otpText = window.settings.hideOTP ? "******" : otpValue
if (window.settings.splitOTP) {
const m = Math.floor(otpText.length/2)
otpText = otpText.substring(0, m) +" "+ otpText.substring(m)
}
clone.querySelector(".otpcode span").textContent = otpText
clone.querySelector(".otpcode span").setAttribute("data-otpvalue", otpValue)
if (account.type === "hotp") {
clone.querySelector(".refreshbutton").setAttribute("data-accountid", account.id)
}
document.querySelector("#otp-list").appendChild(clone)
}
async function stepHOTP(accountid) {
let account = null
for (var i in window.accounts) {
if (window.accounts[i].id == accountid) {
window.accounts[i].counter += 1
account = window.accounts[i]
break
}
}
if (account) {
// Update Locally
const otpValue = getOtpFromAccount(account)
let otpText = window.settings.hideOTP ? "******" : otpValue
if (window.settings.splitOTP) {
const m = Math.floor(otpText.length/2)
otpText = otpText.substring(0, m) +" "+ otpText.substring(m)
}
const refresbutton = $(".refreshbutton[data-accountid='" + accountid +"']");
refresbutton.parent().parent().find(".twelve").find(".otpcode span").text(otpText)
refresbutton.parent().parent().find(".twelve").find(".otpcode span").attr("data-otpvalue", otpValue)
// Update Server
try {
let headers = requestHeaders
headers.set("Content-Type", "application/x-www-form-urlencoded")
const response = await fetch(server+ "/ocs/v2.php/apps/otpmanager/accounts/update-counter", {
method: "POST",
headers: headers,
credentials: "omit",
body: "secret="+ encodeURIComponent(account.secret)
})
const jsonData = await response.json()
if (!response.ok) {
console.log("Failed to update HOTP token on server for id (a): "+ accountid)
}
} catch {
console.log("Failed to update HOTP token on server for id (b): "+ accountid)
}
} else {
console.log("HOTP counter update: Can't find account")
}
}
function displayOtp() {
if (!window.accounts) {
console.log("No accounts???")
// Should display user error and go back to start
}
$("#settings-button").show(300)
$("#otp-list").empty()
$("#otp-container").show()
// Order accounts
sortAccounts(window.settings.sortOn ? window.settings.sortOn : "default", window.settings.sortOrder ? window.settings.sortOrder : "asc")
// Display accounts
window.accounts.forEach(account => {
generateAccountSegment(account)
});
// Copy code on click
$(".otpcode").on("click", function() {
navigator.clipboard.writeText($(this).find("span").attr("data-otpvalue"))
$(this).fadeOut(200).fadeIn(200)
})
// Increase hotp counter on click
$(".refreshbutton").on("click", async function() {
$(this).fadeOut(200)
const accountid = $(this).attr("data-accountid")
await stepHOTP(accountid)
$(this).fadeIn(200)
})
// Search
$("#otp-search input").keyup(searchOtp)
$("#otp-search i").on("click", searchOtp)
if($("#settings-container").is(":hidden")) $("#otp-search input").focus()
}
function searchOtp() {
const term = $("#otp-search input").val().toLowerCase()
$("#otp-list .segment").each(function(i) {
const accountissuer = $(this).find(".accountissuer").text().toLowerCase()
const accountname = $(this).find(".accountname").text().toLowerCase()
if (accountname.includes(term) || accountissuer.includes(term)) {
$(this).show()
} else {
$(this).hide()
}
})
}