2020-12-30 18:35:18 +00:00
import { AppContext , KoaNext , NotificationView } from '../utils/types' ;
2020-12-30 23:50:44 +00:00
import { isApiRequest } from '../utils/requestUtils' ;
import { defaultAdminEmail , defaultAdminPassword , NotificationLevel } from '../db' ;
2020-12-30 18:35:18 +00:00
import { _ } from '@joplin/lib/locale' ;
import Logger from '@joplin/lib/Logger' ;
import * as MarkdownIt from 'markdown-it' ;
2021-01-18 10:13:26 +00:00
import config from '../config' ;
2020-12-30 18:35:18 +00:00
const logger = Logger . create ( 'notificationHandler' ) ;
2021-01-18 10:13:26 +00:00
async function handleChangeAdminPasswordNotification ( ctx : AppContext ) {
if ( ! ctx . owner . is_admin ) return ;
const defaultAdmin = await ctx . models . user ( ) . login ( defaultAdminEmail , defaultAdminPassword ) ;
2021-05-13 18:57:37 +02:00
const notificationModel = ctx . models . notification ( ) ;
2021-01-18 10:13:26 +00:00
if ( defaultAdmin ) {
await notificationModel . add (
2021-05-13 18:57:37 +02:00
ctx . owner . id ,
2021-01-18 10:13:26 +00:00
'change_admin_password' ,
NotificationLevel . Important ,
2021-05-25 11:49:47 +02:00
_ ( 'The default admin password is insecure and has not been changed! [Change it now](%s)' , ctx . models . user ( ) . profileUrl ( ) )
2021-01-18 10:13:26 +00:00
) ;
} else {
2021-05-13 18:57:37 +02:00
await notificationModel . markAsRead ( ctx . owner . id , 'change_admin_password' ) ;
2021-01-18 10:13:26 +00:00
}
if ( config ( ) . database . client === 'sqlite3' && ctx . env === 'prod' ) {
await notificationModel . add (
2021-05-13 18:57:37 +02:00
ctx . owner . id ,
2021-01-18 10:13:26 +00:00
'using_sqlite_in_prod' ,
NotificationLevel . Important ,
'The server is currently using SQLite3 as a database. It is not recommended in production as it is slow and can cause locking issues. Please see the README for information on how to change it.'
) ;
}
}
async function handleSqliteInProdNotification ( ctx : AppContext ) {
if ( ! ctx . owner . is_admin ) return ;
2021-05-13 18:57:37 +02:00
const notificationModel = ctx . models . notification ( ) ;
2021-01-18 10:13:26 +00:00
if ( config ( ) . database . client === 'sqlite3' && ctx . env === 'prod' ) {
await notificationModel . add (
2021-05-13 18:57:37 +02:00
ctx . owner . id ,
2021-01-18 10:13:26 +00:00
'using_sqlite_in_prod' ,
NotificationLevel . Important ,
'The server is currently using SQLite3 as a database. It is not recommended in production as it is slow and can cause locking issues. Please see the README for information on how to change it.'
) ;
}
}
async function makeNotificationViews ( ctx : AppContext ) : Promise < NotificationView [ ] > {
const markdownIt = new MarkdownIt ( ) ;
2021-05-13 18:57:37 +02:00
const notificationModel = ctx . models . notification ( ) ;
2021-01-18 10:13:26 +00:00
const notifications = await notificationModel . allUnreadByUserId ( ctx . owner . id ) ;
const views : NotificationView [ ] = [ ] ;
for ( const n of notifications ) {
views . push ( {
id : n.id ,
messageHtml : markdownIt.render ( n . message ) ,
level : n.level === NotificationLevel . Important ? 'warning' : 'info' ,
closeUrl : notificationModel.closeUrl ( n . id ) ,
} ) ;
}
return views ;
}
// The role of this middleware is to inspect the system and to generate
// notifications for any issue it finds. It is only active for logged in users
// on the website. It is inactive for API calls.
2020-12-30 18:35:18 +00:00
export default async function ( ctx : AppContext , next : KoaNext ) : Promise < void > {
ctx . notifications = [ ] ;
try {
if ( isApiRequest ( ctx ) ) return next ( ) ;
2021-01-18 10:13:26 +00:00
if ( ! ctx . owner ) return next ( ) ;
2020-12-30 18:35:18 +00:00
2021-01-18 10:13:26 +00:00
await handleChangeAdminPasswordNotification ( ctx ) ;
await handleSqliteInProdNotification ( ctx ) ;
ctx . notifications = await makeNotificationViews ( ctx ) ;
2020-12-30 18:35:18 +00:00
} catch ( error ) {
logger . error ( error ) ;
}
return next ( ) ;
}