mirror of
https://github.com/zadam/trilium.git
synced 2026-01-16 11:34:25 +01:00
86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import sql from "../sql.js";
|
|
import optionService from "../options.js";
|
|
import myScryptService from "./my_scrypt.js";
|
|
import { randomSecureToken, toBase64 } from "../utils.js";
|
|
import passwordEncryptionService from "./password_encryption.js";
|
|
import { ChangePasswordResponse } from "@triliumnext/commons";
|
|
|
|
function isPasswordSet() {
|
|
return !!sql.getValue("SELECT value FROM options WHERE name = 'passwordVerificationHash'");
|
|
}
|
|
|
|
function changePassword(currentPassword: string, newPassword: string): ChangePasswordResponse {
|
|
if (!isPasswordSet()) {
|
|
throw new Error("Password has not been set yet, so it cannot be changed. Use 'setPassword' instead.");
|
|
}
|
|
|
|
if (!passwordEncryptionService.verifyPassword(currentPassword)) {
|
|
return {
|
|
success: false,
|
|
message: "Given current password doesn't match hash"
|
|
};
|
|
}
|
|
|
|
sql.transactional(() => {
|
|
const decryptedDataKey = passwordEncryptionService.getDataKey(currentPassword);
|
|
|
|
optionService.setOption("passwordVerificationSalt", randomSecureToken(32));
|
|
optionService.setOption("passwordDerivedKeySalt", randomSecureToken(32));
|
|
|
|
const newPasswordVerificationKey = toBase64(myScryptService.getVerificationHash(newPassword));
|
|
|
|
if (decryptedDataKey) {
|
|
// TODO: what should happen if the decrypted data key is null?
|
|
passwordEncryptionService.setDataKey(newPassword, decryptedDataKey);
|
|
}
|
|
|
|
optionService.setOption("passwordVerificationHash", newPasswordVerificationKey);
|
|
});
|
|
|
|
return {
|
|
success: true
|
|
};
|
|
}
|
|
|
|
function setPassword(password: string): ChangePasswordResponse {
|
|
if (isPasswordSet()) {
|
|
throw new Error("Password is set already. Either change it or perform 'reset password' first.");
|
|
}
|
|
|
|
optionService.createOption("passwordVerificationSalt", randomSecureToken(32), true);
|
|
optionService.createOption("passwordDerivedKeySalt", randomSecureToken(32), true);
|
|
|
|
const passwordVerificationKey = toBase64(myScryptService.getVerificationHash(password));
|
|
optionService.createOption("passwordVerificationHash", passwordVerificationKey, true);
|
|
|
|
// passwordEncryptionService expects these options to already exist
|
|
optionService.createOption("encryptedDataKey", "", true);
|
|
|
|
passwordEncryptionService.setDataKey(password, randomSecureToken(16));
|
|
|
|
return {
|
|
success: true
|
|
};
|
|
}
|
|
|
|
function resetPassword() {
|
|
// user forgot the password,
|
|
sql.transactional(() => {
|
|
optionService.setOption("passwordVerificationSalt", "");
|
|
optionService.setOption("passwordDerivedKeySalt", "");
|
|
optionService.setOption("encryptedDataKey", "");
|
|
optionService.setOption("passwordVerificationHash", "");
|
|
});
|
|
|
|
return {
|
|
success: true
|
|
};
|
|
}
|
|
|
|
export default {
|
|
isPasswordSet,
|
|
changePassword,
|
|
setPassword,
|
|
resetPassword
|
|
};
|