mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 15:11:31 +08: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">
 | 
				
			||||||
 | 
				
			|||||||
@ -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