mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 09:58:32 +02:00
set password from web trilium
This commit is contained in:
parent
4e31af8c84
commit
f92016f9ec
1
db/migrations/0189__delete_username_option.sql
Normal file
1
db/migrations/0189__delete_username_option.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DELETE FROM options WHERE name = 'username';
|
@ -85,14 +85,10 @@ function logoutFromProtectedSession() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function token(req) {
|
function token(req) {
|
||||||
const username = req.body.username;
|
|
||||||
const password = req.body.password;
|
const password = req.body.password;
|
||||||
|
|
||||||
const isUsernameValid = username === optionService.getOption('username');
|
if (!passwordEncryptionService.verifyPassword(password)) {
|
||||||
const isPasswordValid = passwordEncryptionService.verifyPassword(password);
|
return [401, "Incorrect password"];
|
||||||
|
|
||||||
if (!isUsernameValid || !isPasswordValid) {
|
|
||||||
return [401, "Incorrect username/password"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiToken = new ApiToken({
|
const apiToken = new ApiToken({
|
||||||
|
@ -6,7 +6,6 @@ const searchService = require('../../services/search/services/search');
|
|||||||
|
|
||||||
// options allowed to be updated directly in options dialog
|
// options allowed to be updated directly in options dialog
|
||||||
const ALLOWED_OPTIONS = new Set([
|
const ALLOWED_OPTIONS = new Set([
|
||||||
'username', // not exposed for update (not harmful anyway), needed for reading
|
|
||||||
'eraseEntitiesAfterTimeInSeconds',
|
'eraseEntitiesAfterTimeInSeconds',
|
||||||
'protectedSessionTimeout',
|
'protectedSessionTimeout',
|
||||||
'noteRevisionSnapshotTimeInterval',
|
'noteRevisionSnapshotTimeInterval',
|
||||||
|
@ -18,9 +18,9 @@ async function setupNewDocument() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupSyncFromServer(req) {
|
function setupSyncFromServer(req) {
|
||||||
const { syncServerHost, syncProxy, username, password } = req.body;
|
const { syncServerHost, syncProxy, password } = req.body;
|
||||||
|
|
||||||
return setupService.setupSyncFromSyncServer(syncServerHost, syncProxy, username, password);
|
return setupService.setupSyncFromSyncServer(syncServerHost, syncProxy, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSyncSeed(req) {
|
function saveSyncSeed(req) {
|
||||||
|
@ -4,21 +4,48 @@ const utils = require('../services/utils');
|
|||||||
const optionService = require('../services/options');
|
const optionService = require('../services/options');
|
||||||
const myScryptService = require('../services/my_scrypt');
|
const myScryptService = require('../services/my_scrypt');
|
||||||
const log = require('../services/log');
|
const log = require('../services/log');
|
||||||
|
const sqlInit = require("../services/sql_init.js");
|
||||||
|
const optionsInitService = require("../services/options_init.js");
|
||||||
|
|
||||||
function loginPage(req, res) {
|
function loginPage(req, res) {
|
||||||
res.render('login', { failedAuth: false });
|
res.render('login', { failedAuth: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
function setPasswordPage(req, res) {
|
function setPasswordPage(req, res) {
|
||||||
res.render('set_password', { failed: false });
|
res.render('set_password', { error: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPassword(req, res) {
|
||||||
|
if (sqlInit.isPasswordSet()) {
|
||||||
|
return [400, "Password has been already set"];
|
||||||
|
}
|
||||||
|
|
||||||
|
let {password1, password2} = req.body;
|
||||||
|
password1 = password1.trim();
|
||||||
|
password2 = password2.trim();
|
||||||
|
|
||||||
|
let error;
|
||||||
|
|
||||||
|
if (password1 !== password2) {
|
||||||
|
error = "Entered passwords don't match.";
|
||||||
|
} else if (password1.length < 4) {
|
||||||
|
error = "Password must be at least 4 characters long.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
res.render('set_password', { error });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsInitService.initPassword(password1);
|
||||||
|
|
||||||
|
res.redirect('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
function login(req, res) {
|
function login(req, res) {
|
||||||
const userName = optionService.getOption('username');
|
|
||||||
|
|
||||||
const guessedPassword = req.body.password;
|
const guessedPassword = req.body.password;
|
||||||
|
|
||||||
if (req.body.username === userName && verifyPassword(guessedPassword)) {
|
if (verifyPassword(guessedPassword)) {
|
||||||
const rememberMe = req.body.remember_me;
|
const rememberMe = req.body.remember_me;
|
||||||
|
|
||||||
req.session.regenerate(() => {
|
req.session.regenerate(() => {
|
||||||
@ -34,7 +61,7 @@ function login(req, res) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// note that logged IP address is usually meaningless since the traffic should come from a reverse proxy
|
// note that logged IP address is usually meaningless since the traffic should come from a reverse proxy
|
||||||
log.info(`WARNING: Wrong username / password from ${req.ip}, rejecting.`);
|
log.info(`WARNING: Wrong password from ${req.ip}, rejecting.`);
|
||||||
|
|
||||||
res.render('login', {'failedAuth': true});
|
res.render('login', {'failedAuth': true});
|
||||||
}
|
}
|
||||||
@ -60,6 +87,7 @@ function logout(req, res) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
loginPage,
|
loginPage,
|
||||||
setPasswordPage,
|
setPasswordPage,
|
||||||
|
setPassword,
|
||||||
login,
|
login,
|
||||||
logout
|
logout
|
||||||
};
|
};
|
||||||
|
@ -183,7 +183,7 @@ const uploadMiddleware = multer.single('upload');
|
|||||||
function register(app) {
|
function register(app) {
|
||||||
route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index);
|
route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index);
|
||||||
route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage);
|
route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage);
|
||||||
route(GET, '/set_password', [auth.checkAppInitialized], loginRoute.setPasswordPage);
|
route(GET, '/set-password', [auth.checkAppInitialized], loginRoute.setPasswordPage);
|
||||||
|
|
||||||
const loginRateLimiter = rateLimit({
|
const loginRateLimiter = rateLimit({
|
||||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||||
@ -192,6 +192,7 @@ function register(app) {
|
|||||||
|
|
||||||
route(POST, '/login', [loginRateLimiter], loginRoute.login);
|
route(POST, '/login', [loginRateLimiter], loginRoute.login);
|
||||||
route(POST, '/logout', [csrfMiddleware, auth.checkAuth], loginRoute.logout);
|
route(POST, '/logout', [csrfMiddleware, auth.checkAuth], loginRoute.logout);
|
||||||
|
route(POST, '/set-password', [auth.checkAppInitialized], loginRoute.setPassword);
|
||||||
route(GET, '/setup', [], setupRoute.setupPage);
|
route(GET, '/setup', [], setupRoute.setupPage);
|
||||||
|
|
||||||
apiRoute(GET, '/api/tree', treeApiRoute.getTree);
|
apiRoute(GET, '/api/tree', treeApiRoute.getTree);
|
||||||
|
@ -4,8 +4,8 @@ const build = require('./build');
|
|||||||
const packageJson = require('../../package');
|
const packageJson = require('../../package');
|
||||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||||
|
|
||||||
const APP_DB_VERSION = 188;
|
const APP_DB_VERSION = 189;
|
||||||
const SYNC_VERSION = 23;
|
const SYNC_VERSION = 24;
|
||||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -18,7 +18,7 @@ function checkAuth(req, res, next) {
|
|||||||
if (sqlInit.isPasswordSet()) {
|
if (sqlInit.isPasswordSet()) {
|
||||||
res.redirect("login");
|
res.redirect("login");
|
||||||
} else {
|
} else {
|
||||||
res.redirect("set_password");
|
res.redirect("set-password");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -57,7 +57,7 @@ function checkAppInitialized(req, res, next) {
|
|||||||
|
|
||||||
function checkPasswordSet(req, res, next) {
|
function checkPasswordSet(req, res, next) {
|
||||||
if (!utils.isElectron() && !sqlInit.isPasswordSet()) {
|
if (!utils.isElectron() && !sqlInit.isPasswordSet()) {
|
||||||
res.redirect("set_password");
|
res.redirect("set-password");
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
@ -99,10 +99,10 @@ function checkCredentials(req, res, next) {
|
|||||||
const auth = new Buffer.from(header, 'base64').toString();
|
const auth = new Buffer.from(header, 'base64').toString();
|
||||||
const [username, password] = auth.split(/:/);
|
const [username, password] = auth.split(/:/);
|
||||||
|
|
||||||
const dbUsername = optionService.getOption('username');
|
// username is ignored
|
||||||
|
|
||||||
if (dbUsername !== username || !passwordEncryptionService.verifyPassword(password)) {
|
if (!passwordEncryptionService.verifyPassword(password)) {
|
||||||
res.status(401).send('Incorrect username and/or password');
|
res.status(401).send('Incorrect password');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
next();
|
next();
|
||||||
|
@ -12,7 +12,7 @@ function initDocumentOptions() {
|
|||||||
optionService.createOption('documentSecret', utils.randomSecureToken(16), false);
|
optionService.createOption('documentSecret', utils.randomSecureToken(16), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initPassword(username, password) {
|
function initPassword(password) {
|
||||||
optionService.createOption('passwordVerificationSalt', utils.randomSecureToken(32), true);
|
optionService.createOption('passwordVerificationSalt', utils.randomSecureToken(32), true);
|
||||||
optionService.createOption('passwordDerivedKeySalt', utils.randomSecureToken(32), true);
|
optionService.createOption('passwordDerivedKeySalt', utils.randomSecureToken(32), true);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ function exec(opts) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (opts.auth) {
|
if (opts.auth) {
|
||||||
headers['trilium-cred'] = Buffer.from(opts.auth.username + ":" + opts.auth.password).toString('base64');
|
headers['trilium-cred'] = Buffer.from("dummy:" + opts.auth.password).toString('base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = client.request({
|
const request = client.request({
|
||||||
|
@ -55,7 +55,7 @@ async function requestToSyncServer(method, path, body = null) {
|
|||||||
}), timeout);
|
}), timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupSyncFromSyncServer(syncServerHost, syncProxy, username, password) {
|
async function setupSyncFromSyncServer(syncServerHost, syncProxy, password) {
|
||||||
if (sqlInit.isDbInitialized()) {
|
if (sqlInit.isDbInitialized()) {
|
||||||
return {
|
return {
|
||||||
result: 'failure',
|
result: 'failure',
|
||||||
@ -70,10 +70,7 @@ async function setupSyncFromSyncServer(syncServerHost, syncProxy, username, pass
|
|||||||
const resp = await request.exec({
|
const resp = await request.exec({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: syncServerHost + '/api/setup/sync-seed',
|
url: syncServerHost + '/api/setup/sync-seed',
|
||||||
auth: {
|
auth: { password },
|
||||||
username,
|
|
||||||
password
|
|
||||||
},
|
|
||||||
proxy: syncProxy,
|
proxy: syncProxy,
|
||||||
timeout: 30000 // seed request should not take long
|
timeout: 30000 // seed request should not take long
|
||||||
});
|
});
|
||||||
|
@ -31,11 +31,7 @@ function isDbInitialized() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isPasswordSet() {
|
function isPasswordSet() {
|
||||||
const value = sql.getValue("SELECT value FROM options WHERE name = 'passwordVerificationHash'");
|
return !!sql.getValue("SELECT value FROM options WHERE name = 'passwordVerificationHash'");
|
||||||
|
|
||||||
console.log("AAAAAAAAAAAAEEEEEEEEE", value);
|
|
||||||
|
|
||||||
return !!value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initDbConnection() {
|
async function initDbConnection() {
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<a class="nav-link" data-toggle="tab" href="#options-code-notes">Code notes</a>
|
<a class="nav-link" data-toggle="tab" href="#options-code-notes">Code notes</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" data-toggle="tab" href="#options-credentials">Username & password</a>
|
<a class="nav-link" data-toggle="tab" href="#options-credentials">Password</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" data-toggle="tab" href="#options-backup">Backup</a>
|
<a class="nav-link" data-toggle="tab" href="#options-backup">Backup</a>
|
||||||
|
@ -14,17 +14,11 @@
|
|||||||
|
|
||||||
<% if (failedAuth) { %>
|
<% if (failedAuth) { %>
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
Username and / or password are incorrect. Please try again.
|
Password is incorrect. Please try again.
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<form action="login" method="POST">
|
<form action="login" method="POST">
|
||||||
<div class="form-group">
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input id="username" name="username" placeholder="" class="form-control" type="text">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
@ -76,4 +70,4 @@
|
|||||||
|
|
||||||
<link href="libraries/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
<link href="libraries/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -12,15 +12,15 @@
|
|||||||
<div class="col-xs-12 col-sm-10 col-md-6 col-lg-4 col-xl-4 mx-auto" style="padding-top: 25px;">
|
<div class="col-xs-12 col-sm-10 col-md-6 col-lg-4 col-xl-4 mx-auto" style="padding-top: 25px;">
|
||||||
<h1>Set password</h1>
|
<h1>Set password</h1>
|
||||||
|
|
||||||
<% if (failed) { %>
|
<% if (error) { %>
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
Err
|
<%= error %>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<p>Before you can start using Trilium from web, you need to set a password first. You will then use this password to login.</p>
|
<p>Before you can start using Trilium from web, you need to set a password first. You will then use this password to login.</p>
|
||||||
|
|
||||||
<form action="login" method="POST">
|
<form action="set-password" method="POST">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
|
@ -118,10 +118,6 @@
|
|||||||
|
|
||||||
<p><strong>Note:</strong> If you leave proxy setting blank, system proxy will be used (applies to desktop/electron build only)</p>
|
<p><strong>Note:</strong> If you leave proxy setting blank, system proxy will be used (applies to desktop/electron build only)</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<input type="text" id="username" class="form-control" data-bind="value: username" placeholder="Username">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password1">Password</label>
|
<label for="password1">Password</label>
|
||||||
<input type="password" id="password1" class="form-control" data-bind="value: password1" placeholder="Password">
|
<input type="password" id="password1" class="form-control" data-bind="value: password1" placeholder="Password">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user