mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	set password from web trilium
This commit is contained in:
		
							
								
								
									
										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"> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user