diff --git a/.gitignore b/.gitignore
index 1dea14ba..106e4328 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ data/users.db
data/sessions.db
data/kb.db
data/votes.db
+data/backup.tar
Rubbish/
public/images/
public/uploads/
diff --git a/app.js b/app.js
index c502c8a1..ea097277 100644
--- a/app.js
+++ b/app.js
@@ -74,7 +74,7 @@ handlebars = handlebars.create({
var array = keywords.split(','); var links = '';
for(var i = 0; i < array.length; i++){
if(array[i].trim() !== ''){
- links += '' + array[i].trim() + ' | ';
+ links += '' + array[i].trim() + ' | ';
}
}return links.substring(0, links.length - 1);
}
@@ -217,7 +217,7 @@ app.use(session({
cookie: {
path: '/',
httpOnly: true,
- maxAge: 3600000 * 24
+ maxAge: 3600000 * 24 * 30
},
store: new Nedb_store({
filename: 'data/sessions.db'
diff --git a/config/config.json b/config/config.json
index 7473dd9c..f10b5f04 100644
--- a/config/config.json
+++ b/config/config.json
@@ -1,41 +1,41 @@
{
"settings": {
"route_name": "kb",
- "num_top_results": "10",
+ "num_top_results": "8",
"date_format": "DD/MM/YYYY h:mmA",
"show_view_count": true,
- "update_view_count_logged_in": false,
+ "update_view_count_logged_in": true,
"show_published_date": true,
"sort_by": {
"field": "kb_viewcount",
"order": -1
},
- "website_title": "openKB",
+ "website_title": "RemusKB",
"show_featured_articles": true,
"show_featured_in_article": false,
"featured_articles_count": "4",
- "password_protect": false,
- "show_kb_meta": true,
- "suggest_allowed": true,
- "show_author_email": true,
- "mermaid": false,
- "mathjax": false,
+ "password_protect": true,
+ "show_kb_meta": false,
+ "suggest_allowed": false,
+ "show_author_email": false,
+ "mermaid": true,
+ "mathjax": true,
"mathjax_input_mode": "TeX-MML-AM_CHTML",
"app_context": "",
"links_blank_page": true,
"database": {
"type": "embedded"
},
- "allow_voting": true,
+ "allow_voting": false,
"google_analytics": "",
"theme": "",
"show_logon": true,
"add_header_anchors": false,
"typeahead_search": true,
- "index_article_body": false,
+ "index_article_body": true,
"enable_spellchecker": true,
- "show_website_logo": true,
- "website_description": "openKB is an Open Source Node.js Markdown based knowledge base/FAQ/Wiki app with powerful lunr search",
+ "show_website_logo": false,
+ "website_description": "RemusKB needs no description. ",
"article_versioning": false,
"api_auth_token": "",
"api_allowed": false,
diff --git a/locales/en.js b/locales/en.js
index 38a69ebd..9de7ee3a 100644
--- a/locales/en.js
+++ b/locales/en.js
@@ -1,36 +1,44 @@
{
+ "Search the knowledge base": "Search the knowledge base",
+ "Search": "Search",
+ "Featured articles": "Featured articles",
+ "Topic": "Topic",
+ "Date": "Date",
+ "View count": "View count",
+ "Powered by": "Powered by",
"Toggle navigation": "Toggle navigation",
"Users": "Users",
"New": "New",
"Edit": "Edit",
"My account": "My account",
"Article": "Article",
+ "Admin": "Admin",
"Settings": "Settings",
"Files": "Files",
+ "Import": "Import",
"Export": "Export",
"Cleanup files": "Cleanup files",
"Logout": "Logout",
- "Powered by": "Powered by",
+ "Cannot find module 'markdown-it-sub'": "Cannot find module 'markdown-it-sub'",
+ "Login": "Login",
+ "Not Found": "Not Found",
+ "Top articles": "Top articles",
+ "403 - Forbidden": "403 - Forbidden",
"Home": "Home",
- "Articles": "Articles",
- "Filter articles": "Filter articles",
- "Filter": "Filter",
- "Reset": "Reset",
- "All": "All",
+ "Articles by Tag": "Articles by Tag",
"Published": "Published",
"Recent": "Recent",
"Are you sure you want to delete this article?": "Are you sure you want to delete this article?",
- "Search": "Search",
- "Featured articles": "Featured articles",
- "Top articles": "Top articles",
- "Suggest": "Suggest",
- "Login": "Login",
- "Please sign in": "Please sign in",
- "email address": "email address",
- "Password": "Password",
- "Sign in": "Sign in",
+ "Results for": "Results for",
+ "ifboth doesn't match if - 23:4": "ifboth doesn't match if - 23:4",
+ "options.fn is not a function": "options.fn is not a function",
+ "((helpers.routeType || (depth0 && depth0.routeType)) || alias2).call is not a function": "((helpers.routeType || (depth0 && depth0.routeType)) || alias2).call is not a function",
+ "No results found": "No results found",
+ "Parse error on line 72:\n...{{this.kb_title}} {{__\", has Topics \"}} \n-----------------------^\nExpecting 'ID', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'INVALID'": "Parse error on line 72:\n...{{this.kb_title}} {{__\", has Topics \"}} \n-----------------------^\nExpecting 'ID', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'INVALID'",
+ ", has Topics ": ", has Topics ",
"Website": "Website",
"Display": "Display",
+ "Style": "Style",
"Update": "Update",
"Website title": "Website title",
"The title of your website": "The title of your website",
@@ -39,19 +47,21 @@
"Show website logo": "Show website logo",
"true": "true",
"false": "false",
- "Controls whether to show the 'Website title' text or a logo located: '/public/logo.png' (by default)": "Controls whether to show the 'Website title' text or a logo located: '/public/logo.png' (by default)",
+ "Controls whether to show the \"Website title\" text or a logo located: \"/public/logo.png\" (by default)": "Controls whether to show the \"Website title\" text or a logo located: \"/public/logo.png\" (by default)",
"Website context/base URL": "Website context/base URL",
"Allows for the website to be run from a non root path. Eg: http://127.0.0.1:4444/openkb/": "Allows for the website to be run from a non root path. Eg: http://127.0.0.1:4444/openkb/",
"Allow API access": "Allow API access",
"Whether to allow API access to insert articles - See documentation for further information": "Whether to allow API access to insert articles - See documentation for further information",
"API access token": "API access token",
- "Requires 'Allow API access' to be set to 'true'. The value is the access token required to access the public API. Please set to a hard to guess value": "Requires 'Allow API access' to be set to 'true'. The value is the access token required to access the public API. Please set to a hard to guess value",
+ "Requires \"Allow API access\" to be set to \"true\". The value is the access token required to access the public API. Please set to a hard to guess value": "Requires \"Allow API access\" to be set to \"true\". The value is the access token required to access the public API. Please set to a hard to guess value",
"Password protect": "Password protect",
- "Setting to 'true' will require a user to login before viewing any pages": "Setting to 'true' will require a user to login before viewing any pages",
+ "Setting to \"true\" will require a user to login before viewing any pages": "Setting to \"true\" will require a user to login before viewing any pages",
"Index article body": "Index article body",
"Whether to add the body of your articles to the search index (requires restart)": "Whether to add the body of your articles to the search index (requires restart)",
"Select a theme": "Select a theme",
"The theme to use for public facing pages. Leave blank for default": "The theme to use for public facing pages. Leave blank for default",
+ "Select a language": "Select a language",
+ "The language to use for public facing pages. Leave blank for default (English)": "The language to use for public facing pages. Leave blank for default (English)",
"Show logon link": "Show logon link",
"Whether to show/hide the logon link in the top right of screen": "Whether to show/hide the logon link in the top right of screen",
"Date format": "Date format",
@@ -59,13 +69,13 @@
"Article suggestions allowed": "Article suggestions allowed",
"If enabled non authenticated users can submit article suggestions for approval": "If enabled non authenticated users can submit article suggestions for approval",
"Google analytics code": "Google analytics code",
- "Adds Google Analytics to public facing pages. Include the entire code from Google including the <script> tags": "Adds Google Analytics to public facing pages. Include the entire code from Google including the <script> tags",
+ "Adds Google Analytics to public facing pages. Include the entire code from Google including the
+
diff --git a/public/themes/tocbot/views/layouts/layout.hbs b/public/themes/tocbot/views/layouts/layout.hbs
new file mode 100644
index 00000000..58f4b79a
--- /dev/null
+++ b/public/themes/tocbot/views/layouts/layout.hbs
@@ -0,0 +1,178 @@
+
+
+
+ {{#if result.kb_seo_title}}
+ {{result.kb_seo_title}}
+
+ {{else}}
+ {{#if result.kb_title}}
+ {{result.kb_title}}
+
+ {{else}}
+ {{title}}
+
+ {{/if}}
+ {{/if}}
+
+
+
+ {{#if result.kb_seo_description}}
+
+
+ {{else}}
+ {{#if result.kb_body}}
+
+
+ {{else}}
+ {{#ifCond homepage '===' true}}
+
+
+ {{else}}
+
+
+ {{/ifCond}}
+ {{/if}}
+ {{/if}}
+ {{#if result.kb_keywords}}
+
+ {{else}}
+
+ {{/if}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{#ifCond title '===' 'Settings'}}
+
+ {{/ifCond}}
+
+ {{#ifCond config.settings.mermaid '===' true}}
+
+ {{/ifCond}}
+ {{#ifCond config.settings.mathjax '===' true}}
+
+
+ {{/ifCond}}
+
+
+
+
+
+
+
+
+
+ {{#ifCond config.settings.typeahead_search '===' true}}
+
+ {{/ifCond}}
+
+
+
+ {{#ifCond user_page '===' true}}
+
+ {{#if config.settings.google_analytics}}
+ {{{config.settings.google_analytics}}}
+ {{/if}}
+ {{/ifCond}}
+
+
+
+
+
+
+
+ {{{body}}}
+
+
+
+
+
+
+ {{#if show_footer}}
+
+ {{/if}}
+
+
diff --git a/routes/index.js b/routes/index.js
index a077495d..1932e585 100644
--- a/routes/index.js
+++ b/routes/index.js
@@ -13,1581 +13,1710 @@ var appDir = path.dirname(require('require-main-filename')());
// The homepage of the site
router.get('/', common.restrict, function (req, res, next){
- var db = req.app.db;
- common.config_expose(req.app);
- var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
-
- // set the template dir
- common.setTemplateDir('user', req);
-
- // get sortBy from config, set to 'kb_viewcount' if nothing found
- var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
- var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
- var sortBy = {};
- sortBy[sortByField] = sortByOrder;
-
- // get the top results based on sort order
- common.dbQuery(db.kb, {kb_published: 'true'}, sortBy, config.settings.num_top_results, function (err, top_results){
- common.dbQuery(db.kb, {kb_published: 'true', kb_featured: 'true'}, sortBy, featuredCount, function (err, featured_results){
- res.render('index', {
- title: 'openKB',
- user_page: true,
- homepage: true,
- top_results: top_results,
- featured_results: featured_results,
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config,
- current_url: req.protocol + '://' + req.get('host') + req.app_context,
- fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
- helpers: req.handlebars,
- show_footer: 'show_footer'
- });
- });
- });
+
+ var db = req.app.db;
+ common.config_expose(req.app);
+ var classy = require('../public/javascripts/markdown-it-classy');
+ var markdownit = req.markdownit;
+ markdownit.use(classy);
+
+ var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
+
+ // set the template dir
+ common.setTemplateDir('user', req);
+
+ // get sortBy from config, set to 'kb_viewcount' if nothing found
+ var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
+ var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
+ var sortBy = {};
+ sortBy[sortByField] = sortByOrder;
+
+ // get the homepage
+ common.dbQuery(db.kb, {kb_published: 'true', kb_title: 'Homepage'}, sortBy, config.settings.num_top_results, function (err, top_results){
+ // if no page with title Homepage can be found:
+ if(top_results.length < 1){
+ common.dbQuery(db.kb, {kb_published: 'true', kb_featured: 'true'}, sortBy, featuredCount, function (err, featured_results){
+ res.render('homepage', {
+ title: 'Remus KB Homepage',
+ user_page: true,
+ homepage: true,
+ featured_results: featured_results,
+ session: req.session,
+ kb_body: 'Empty Homepage! Create an article with the title "Homepage" and it will appear here. ',
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ current_url: req.protocol + '://' + req.get('host') + req.app_context,
+ fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
+ helpers: req.handlebars,
+ show_footer: 'show_footer'
+ });
+ });
+ }
+ else{
+ common.dbQuery(db.kb, {kb_published: 'true', kb_featured: 'true'}, sortBy, featuredCount, function (err, featured_results){
+ res.render('homepage', {
+ title: 'Remus KB Homepage',
+ user_page: true,
+ homepage: true,
+ result: top_results[0],
+ kb_body: common.sanitizeHTML(markdownit.render(top_results[0].kb_body)),
+ featured_results: featured_results,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ current_url: req.protocol + '://' + req.get('host') + req.app_context,
+ fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
+ helpers: req.handlebars,
+ show_footer: 'show_footer'
+ });
+ });
+ }
+ });
});
router.post('/protected/action', function (req, res){
- var db = req.app.db;
- // get article
- db.kb.findOne({kb_published: 'true', _id: common.getId(req.body.kb_id)}, function (err, result){
- // check password
- if(req.body.password === result.kb_password){
- // password correct. Allow viewing the article this time
- req.session.pw_validated = 'true';
- res.redirect(req.header('Referer'));
- }else{
- // password incorrect
- req.session.pw_validated = null;
- res.render('error', {message: 'Password incorrect. Please try again.', helpers: req.handlebars, config: config});
- }
- });
+ var db = req.app.db;
+ // get article
+ db.kb.findOne({kb_published: 'true', _id: common.getId(req.body.kb_id)}, function (err, result){
+ // check password
+ if(req.body.password === result.kb_password){
+ // password correct. Allow viewing the article this time
+ req.session.pw_validated = 'true';
+ res.redirect(req.header('Referer'));
+ }else{
+ // password incorrect
+ req.session.pw_validated = null;
+ res.render('error', {message: 'Password incorrect. Please try again.', helpers: req.handlebars, config: config});
+ }
+ });
});
router.post('/search_api', function (req, res){
- var db = req.app.db;
- var index = req.app.index;
-
- // we strip the ID's from the lunr index search
- var index_id_array = [];
- index.search(req.body.searchTerm).forEach(function (id){
- // if mongoDB we use ObjectID's, else normal string ID's
- if(config.settings.database.type !== 'embedded'){
- index_id_array.push(common.getId(id.ref));
- }else{
- index_id_array.push(id.ref);
- }
- });
-
- common.dbQuery(db.kb, {_id: {$in: index_id_array}, kb_published: 'true', kb_versioned_doc: {$ne: true}}, null, null, function (err, results){
- if(err){
- return res.status(400).json({});
- }
- return res.status(200).json(results);
- });
+ var db = req.app.db;
+ var index = req.app.index;
+
+ // we strip the ID's from the lunr index search
+ var index_id_array = [];
+ index.search(req.body.searchTerm).forEach(function (id){
+ // if mongoDB we use ObjectID's, else normal string ID's
+ if(config.settings.database.type !== 'embedded'){
+ index_id_array.push(common.getId(id.ref));
+ }else{
+ index_id_array.push(id.ref);
+ }
+ });
+
+ common.dbQuery(db.kb, {_id: {$in: index_id_array}, kb_published: 'true', kb_versioned_doc: {$ne: true}}, null, null, function (err, results){
+ if(err){
+ return res.status(400).json({});
+ }
+ return res.status(200).json(results);
+ });
});
// vote on articles
router.post('/vote', function (req, res){
- var db = req.app.db;
-
- // if voting allowed
- if(config.settings.allow_voting === true){
- // check if voted
- db.votes.findOne({$and: [{doc_id: req.body.doc_id}, {session_id: req.sessionID}]}, function (err, result){
- // if not voted
- if(!result){
- var vote = req.body.vote_type === 'upvote' ? 1 : -1;
- // update kb vote
- db.kb.update({_id: common.getId(req.body.doc_id)}, {$inc: {kb_votes: vote}}, function (err, numReplaced){
- // insert session id into table to stop muli-voters
- db.votes.insert({doc_id: req.body.doc_id, session_id: req.sessionID}, function (err, newDoc){
- res.writeHead(200, {'Content-Type': 'application/text'});
- res.end('Vote successful');
- });
- });
- }else{
- // User has already voted
- res.writeHead(404, {'Content-Type': 'application/text'});
- res.end('User already voted');
- }
- });
- }else{
- // Voting not allowed
- res.writeHead(404, {'Content-Type': 'application/text'});
- res.end('Voting now allowed');
- }
+ var db = req.app.db;
+
+ // if voting allowed
+ if(config.settings.allow_voting === true){
+ // check if voted
+ db.votes.findOne({$and: [{doc_id: req.body.doc_id}, {session_id: req.sessionID}]}, function (err, result){
+ // if not voted
+ if(!result){
+ var vote = req.body.vote_type === 'upvote' ? 1 : -1;
+ // update kb vote
+ db.kb.update({_id: common.getId(req.body.doc_id)}, {$inc: {kb_votes: vote}}, function (err, numReplaced){
+ // insert session id into table to stop muli-voters
+ db.votes.insert({doc_id: req.body.doc_id, session_id: req.sessionID}, function (err, newDoc){
+ res.writeHead(200, {'Content-Type': 'application/text'});
+ res.end('Vote successful');
+ });
+ });
+ }else{
+ // User has already voted
+ res.writeHead(404, {'Content-Type': 'application/text'});
+ res.end('User already voted');
+ }
+ });
+ }else{
+ // Voting not allowed
+ res.writeHead(404, {'Content-Type': 'application/text'});
+ res.end('Voting now allowed');
+ }
});
// Render a version of the article to logged in users
router.get('/' + config.settings.route_name + '/:id/version', common.restrict, function (req, res){
- var db = req.app.db;
- common.config_expose(req.app);
- var classy = require('../public/javascripts/markdown-it-classy');
- var markdownit = req.markdownit;
- markdownit.use(classy);
-
- // check for logged in user
- if(!req.session.user){
- res.render('error', {message: '404 - Page not found', helpers: req.handlebars, config: config});
- return;
- }
-
- // get sortBy from config, set to 'kb_viewcount' if nothing found
- var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
- var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
- var sortBy = {};
- sortBy[sortByField] = sortByOrder;
-
- var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
-
- db.kb.findOne({_id: common.getId(req.params.id)}, function (err, result){
- // show the view
- common.dbQuery(db.kb, {kb_published: 'true', kb_versioned_doc: {$eq: true}}, sortBy, featuredCount, function (err, featured_results){
- res.render('kb', {
- title: result.kb_title,
- result: result,
- user_page: true,
- kb_body: common.sanitizeHTML(markdownit.render(result.kb_body)),
- featured_results: featured_results,
- config: config,
- session: req.session,
- current_url: req.protocol + '://' + req.get('host') + req.app_context,
- fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- helpers: req.handlebars,
- show_footer: 'show_footer'
- });
- });
- });
+ var db = req.app.db;
+ common.config_expose(req.app);
+ var classy = require('../public/javascripts/markdown-it-classy');
+ var markdownit = req.markdownit;
+ markdownit.use(classy);
+
+ // check for logged in user
+ if(!req.session.user){
+ res.render('error', {message: '404 - Page not found', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ // get sortBy from config, set to 'kb_viewcount' if nothing found
+ var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
+ var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
+ var sortBy = {};
+ sortBy[sortByField] = sortByOrder;
+
+ var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
+
+ db.kb.findOne({_id: common.getId(req.params.id)}, function (err, result){
+ // show the view
+ common.dbQuery(db.kb, {kb_published: 'true', kb_versioned_doc: {$eq: true}}, sortBy, featuredCount, function (err, featured_results){
+ res.render('kb', {
+ title: result.kb_title,
+ result: result,
+ user_page: true,
+ kb_body: common.sanitizeHTML(markdownit.render(result.kb_body)),
+ featured_results: featured_results,
+ config: config,
+ session: req.session,
+ current_url: req.protocol + '://' + req.get('host') + req.app_context,
+ fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ helpers: req.handlebars,
+ show_footer: 'show_footer'
+ });
+ });
+ });
});
+// Render article
router.get('/' + config.settings.route_name + '/:id', common.restrict, function (req, res){
- var db = req.app.db;
- common.config_expose(req.app);
- var classy = require('../public/javascripts/markdown-it-classy');
- var markdownit = req.markdownit;
- markdownit.use(classy);
-
- var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
-
- // set the template dir
- common.setTemplateDir('user', req);
-
- // get sortBy from config, set to 'kb_viewcount' if nothing found
- var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
- var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
- var sortBy = {};
- sortBy[sortByField] = sortByOrder;
-
- db.kb.findOne({$or: [{_id: common.getId(req.params.id)}, {kb_permalink: req.params.id}], kb_versioned_doc: {$ne: true}}, function (err, result){
- // render 404 if page is not published
- if(result == null || result.kb_published === 'false'){
- res.render('error', {message: '404 - Page not found', helpers: req.handlebars, config: config});
- }else{
- // check if has a password
- if(result.kb_password){
- if(result.kb_password !== ''){
- if(req.session.pw_validated === 'false' || req.session.pw_validated === undefined || req.session.pw_validated == null){
- res.render('protected_kb', {
- title: 'Protected Article',
- result: result,
- config: config,
- session: req.session,
- helpers: req.handlebars
- });
- return;
- }
- }
- }
-
- // if article is set to private, redirect to login
- if(typeof result.kb_visible_state !== 'undefined' && result.kb_visible_state === 'private'){
- if(!req.session.user){
- req.session.refer_url = req.originalUrl;
- res.redirect('/login');
- return;
- }
- }
-
- // add to old view count
- var old_viewcount = result.kb_viewcount;
- if(old_viewcount == null){
- old_viewcount = 0;
- }
-
- var new_viewcount = old_viewcount;
- // increment if the user is logged in and if settings say so
- if(req.session.user && config.settings.update_view_count_logged_in){
- new_viewcount = old_viewcount + 1;
- }
-
- // increment if the user is a guest and not logged in
- if(!req.session.user){
- new_viewcount = old_viewcount + 1;
- }
-
- // update kb_viewcount
- db.kb.update({$or: [{_id: common.getId(req.params.id)}, {kb_permalink: req.params.id}]},
- {
- $set: {kb_viewcount: new_viewcount}
- }, {multi: false}, function (err, numReplaced){
- // clear session auth and render page
- req.session.pw_validated = null;
-
- // show the view
- common.dbQuery(db.kb, {kb_published: 'true'}, sortBy, featuredCount, function (err, featured_results){
- res.render('kb', {
- title: result.kb_title,
- result: result,
- user_page: true,
- kb_body: common.sanitizeHTML(markdownit.render(result.kb_body)),
- featured_results: featured_results,
- config: config,
- session: req.session,
- current_url: req.protocol + '://' + req.get('host') + req.app_context,
- fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- helpers: req.handlebars,
- show_footer: 'show_footer'
- });
- });
- });
- }
- });
+ var db = req.app.db;
+ common.config_expose(req.app);
+ var classy = require('../public/javascripts/markdown-it-classy');
+
+ // my custom plugins
+ var video = require('markdown-it-video');
+
+ var markdownit = req.markdownit;
+ markdownit.use(classy);
+
+ markdownit.use(video);
+
+ var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
+
+ // set the template dir
+ common.setTemplateDir('user', req);
+
+ // get sortBy from config, set to 'kb_viewcount' if nothing found
+ var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
+ var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
+ var sortBy = {};
+ sortBy[sortByField] = sortByOrder;
+
+ db.kb.findOne({$or: [{_id: common.getId(req.params.id)}, {kb_permalink: req.params.id}], kb_versioned_doc: {$ne: true}}, function (err, result){
+ // render 404 if page is not published
+ if(result == null || result.kb_published === 'false'){
+ res.render('error', {message: '404 - Page not found', helpers: req.handlebars, config: config});
+ }else{
+ // check if has a password
+ if(result.kb_password){
+ if(result.kb_password !== ''){
+ if(req.session.pw_validated === 'false' || req.session.pw_validated === undefined || req.session.pw_validated == null){
+ res.render('protected_kb', {
+ title: 'Protected Article',
+ result: result,
+ config: config,
+ session: req.session,
+ helpers: req.handlebars
+ });
+ return;
+ }
+ }
+ }
+
+ // if article is set to private, redirect to login
+ if(typeof result.kb_visible_state !== 'undefined' && result.kb_visible_state === 'private'){
+ if(!req.session.user){
+ req.session.refer_url = req.originalUrl;
+ res.redirect('/login');
+ return;
+ }
+ }
+
+ // add to old view count
+ var old_viewcount = result.kb_viewcount;
+ if(old_viewcount == null){
+ old_viewcount = 0;
+ }
+
+ var new_viewcount = old_viewcount;
+ // increment if the user is logged in and if settings say so
+ if(req.session.user && config.settings.update_view_count_logged_in){
+ new_viewcount = old_viewcount + 1;
+ }
+
+ // increment if the user is a guest and not logged in
+ if(!req.session.user){
+ new_viewcount = old_viewcount + 1;
+ }
+
+ // update kb_viewcount
+ db.kb.update({$or: [{_id: common.getId(req.params.id)}, {kb_permalink: req.params.id}]},
+ {
+ $set: {kb_viewcount: new_viewcount}
+ }, {multi: false}, function (err, numReplaced){
+ // clear session auth and render page
+ req.session.pw_validated = null;
+
+ // show the view
+ common.dbQuery(db.kb, {kb_published: 'true'}, sortBy, featuredCount, function (err, featured_results){
+ res.render('kb', {
+ title: result.kb_title,
+ result: result,
+ user_page: true,
+ kb_body: common.sanitizeHTML(markdownit.render(result.kb_body)),
+ featured_results: featured_results,
+ config: config,
+ session: req.session,
+ current_url: req.protocol + '://' + req.get('host') + req.app_context,
+ fullUrl: req.protocol + '://' + req.get('host') + req.originalUrl,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ helpers: req.handlebars,
+ show_footer: 'show_footer'
+ });
+ });
+ });
+ }
+ });
});
// render the settings page
router.get('/settings', common.restrict, function (req, res){
- var junk = require('junk');
-
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- // path to themes
- var themePath = path.join(__dirname, '../public/themes');
-
- fs.readdir(themePath, function (err, files){
- res.render('settings', {
- title: 'Settings',
- session: req.session,
- themes: files.filter(junk.not),
- locale: Object.keys(req.i18n.locales),
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config,
- helpers: req.handlebars
- });
- });
+ var junk = require('junk');
+
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ // path to themes
+ var themePath = path.join(__dirname, '../public/themes');
+
+ fs.readdir(themePath, function (err, files){
+ res.render('settings', {
+ title: 'Settings',
+ session: req.session,
+ themes: files.filter(junk.not),
+ locale: Object.keys(req.i18n.locales),
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ helpers: req.handlebars
+ });
+ });
});
// update the settings
router.post('/update_settings', common.restrict, function (req, res){
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- // get the new settings
- var settings = req.body;
-
- // possible boolean type values
- var booleanArray = [true, 'true', false, 'false'];
-
- // loop settings, update config
- for(var key in settings){
- if(Object.prototype.hasOwnProperty.call(settings, key)){
- var settingValue = settings[key];
- // check for style keys
- if(key.split('.')[0] === 'style'){
- config.settings.style[key.split('.')[1]] = settingValue;
- }else{
- // if true/false, convert to boolean - TODO: Figure a better way of doing this?
- if(booleanArray.indexOf(settingValue) > -1){
- settingValue = (settingValue === 'true');
- }
- config.settings[key] = settingValue;
- }
- }
- }
-
- // write settings to file
- var dir = path.join(__dirname, '..', 'config');
- if(!fs.existsSync(dir)){
- fs.mkdirSync(dir);
- }
- fs.writeFileSync(path.join(dir, 'config.json'), JSON.stringify(config, null, 4), 'utf8');
-
- if(config.settings.locale){
- req.i18n.setLocale(config.settings.locale);
- res.cookie('locale', config.settings.locale);
- req.i18n.setLocaleFromCookie();
- }
-
- // set notification
- req.session.message = req.i18n.__('Settings successfully updated.');
- req.session.message_type = 'success';
-
- // redirect back
- res.redirect(req.app_context + '/settings');
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ // get the new settings
+ var settings = req.body;
+
+ // possible boolean type values
+ var booleanArray = [true, 'true', false, 'false'];
+
+ // loop settings, update config
+ for(var key in settings){
+ if(Object.prototype.hasOwnProperty.call(settings, key)){
+ var settingValue = settings[key];
+ // check for style keys
+ if(key.split('.')[0] === 'style'){
+ config.settings.style[key.split('.')[1]] = settingValue;
+ }else{
+ // if true/false, convert to boolean - TODO: Figure a better way of doing this?
+ if(booleanArray.indexOf(settingValue) > -1){
+ settingValue = (settingValue === 'true');
+ }
+ config.settings[key] = settingValue;
+ }
+ }
+ }
+
+ // write settings to file
+ var dir = path.join(__dirname, '..', 'config');
+ if(!fs.existsSync(dir)){
+ fs.mkdirSync(dir);
+ }
+ fs.writeFileSync(path.join(dir, 'config.json'), JSON.stringify(config, null, 4), 'utf8');
+
+ if(config.settings.locale){
+ req.i18n.setLocale(config.settings.locale);
+ res.cookie('locale', config.settings.locale);
+ req.i18n.setLocaleFromCookie();
+ }
+
+ // set notification
+ req.session.message = req.i18n.__('Settings successfully updated.');
+ req.session.message_type = 'success';
+
+ // redirect back
+ res.redirect(req.app_context + '/settings');
});
// resets the view count of a given article ID
router.get('/' + config.settings.route_name + '/resetviewCount/:id', common.restrict, function (req, res){
- var db = req.app.db;
- db.kb.update({_id: common.getId(req.params.id)}, {$set: {kb_viewcount: 0}}, {multi: false}, function (err, numReplaced){
- if(err){
- req.session.message = req.i18n.__('View count could not be reset. Try again.');
- req.session.message_type = 'danger';
- }else{
- req.session.message = req.i18n.__('View count successfully reset to zero.');
- req.session.message_type = 'success';
- }
-
- // redirect to new doc
- res.redirect(req.app_context + '/edit/' + req.params.id);
- });
+ var db = req.app.db;
+ db.kb.update({_id: common.getId(req.params.id)}, {$set: {kb_viewcount: 0}}, {multi: false}, function (err, numReplaced){
+ if(err){
+ req.session.message = req.i18n.__('View count could not be reset. Try again.');
+ req.session.message_type = 'danger';
+ }else{
+ req.session.message = req.i18n.__('View count successfully reset to zero.');
+ req.session.message_type = 'success';
+ }
+
+ // redirect to new doc
+ res.redirect(req.app_context + '/edit/' + req.params.id);
+ });
});
// resets the vote count of a given article ID
router.get('/' + config.settings.route_name + '/resetvoteCount/:id', common.restrict, function (req, res){
- var db = req.app.db;
- db.kb.update({_id: common.getId(req.params.id)}, {$set: {kb_votes: 0}}, {multi: false}, function (err, numReplaced){
- if(err){
- req.session.message = req.i18n.__('Vote count could not be reset. Try again.');
- req.session.message_type = 'danger';
- }else{
- req.session.message = req.i18n.__('Vote count successfully reset to zero.');
- req.session.message_type = 'success';
- }
-
- // redirect to new doc
- res.redirect(req.app_context + '/edit/' + req.params.id);
- });
+ var db = req.app.db;
+ db.kb.update({_id: common.getId(req.params.id)}, {$set: {kb_votes: 0}}, {multi: false}, function (err, numReplaced){
+ if(err){
+ req.session.message = req.i18n.__('Vote count could not be reset. Try again.');
+ req.session.message_type = 'danger';
+ }else{
+ req.session.message = req.i18n.__('Vote count successfully reset to zero.');
+ req.session.message_type = 'success';
+ }
+
+ // redirect to new doc
+ res.redirect(req.app_context + '/edit/' + req.params.id);
+ });
});
// render the editor
router.get('/edit/:id', common.restrict, function (req, res){
- var db = req.app.db;
- common.config_expose(req.app);
- db.kb.findOne({_id: common.getId(req.params.id), kb_versioned_doc: {$ne: true}}, function (err, result){
- if(!result){
- res.render('error', {message: '404 - Page not found', helpers: req.handlebars, config: config});
- return;
- }
-
- common.dbQuery(db.kb, {kb_parent_id: req.params.id}, {kb_last_updated: -1}, 20, function (err, versions){
- res.render('edit', {
- title: 'Edit article',
- result: result,
- versions: versions,
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config,
- editor: true,
- helpers: req.handlebars
- });
- });
- });
+ var db = req.app.db;
+ common.config_expose(req.app);
+ db.kb.findOne({_id: common.getId(req.params.id), kb_versioned_doc: {$ne: true}}, function (err, result){
+ if(!result){
+ res.render('error', {message: '404 - Page not found', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ common.dbQuery(db.kb, {kb_parent_id: req.params.id}, {kb_last_updated: -1}, 20, function (err, versions){
+ res.render('edit', {
+ title: 'Edit article',
+ result: result,
+ versions: versions,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ editor: true,
+ helpers: req.handlebars
+ });
+ });
+ });
});
// insert new KB form action
router.post('/insert_kb', common.restrict, function (req, res){
- var db = req.app.db;
- var lunr_index = req.app.index;
-
- var doc = {
- kb_permalink: req.body.frm_kb_permalink,
- kb_title: req.body.frm_kb_title,
- kb_body: req.body.frm_kb_body,
- kb_published: req.body.frm_kb_published,
- kb_keywords: req.body.frm_kb_keywords,
- kb_published_date: new Date(),
- kb_last_updated: new Date(),
- kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
- kb_author: req.session.users_name,
- kb_author_email: req.session.user
- };
-
- db.kb.count({'kb_permalink': req.body.frm_kb_permalink}, function (err, kb){
- if(kb > 0 && req.body.frm_kb_permalink !== ''){
- // permalink exits
- req.session.message = req.i18n.__('Permalink already exists. Pick a new one.');
- req.session.message_type = 'danger';
-
- // keep the current stuff
- req.session.kb_title = req.body.frm_kb_title;
- req.session.kb_body = req.body.frm_kb_body;
- req.session.kb_keywords = req.body.frm_kb_keywords;
- req.session.kb_permalink = req.body.frm_kb_permalink;
-
- // redirect to insert
- res.redirect(req.app_context + '/insert');
- }else{
- db.kb.insert(doc, function (err, newDoc){
- if(err){
- console.error('Error inserting document: ' + err);
-
- // keep the current stuff
- req.session.kb_title = req.body.frm_kb_title;
- req.session.kb_body = req.body.frm_kb_body;
- req.session.kb_keywords = req.body.frm_kb_keywords;
- req.session.kb_permalink = req.body.frm_kb_permalink;
-
- req.session.message = req.i18n.__('Error') + ': ' + err;
- req.session.message_type = 'danger';
-
- // redirect to insert
- res.redirect(req.app_context + '/insert');
- }else{
- // setup keywords
- var keywords = '';
- if(req.body.frm_kb_keywords !== undefined){
- keywords = req.body.frm_kb_keywords.toString().replace(/,/g, ' ');
- }
-
- // get the new ID
- var newId = newDoc._id;
- if(config.settings.database.type !== 'embedded'){
- newId = newDoc.insertedIds[0];
- }
-
- // create lunr doc
- var lunr_doc = {
- kb_title: req.body.frm_kb_title,
- kb_keywords: keywords,
- id: newId
- };
-
- console.log('lunr_doc', lunr_doc);
-
- // if index body is switched on
- if(config.settings.index_article_body === true){
- lunr_doc['kb_body'] = req.body.frm_kb_body;
- }
-
- // add to lunr index
- lunr_index.add(lunr_doc);
-
- req.session.message = req.i18n.__('New article successfully created');
- req.session.message_type = 'success';
-
- // redirect to new doc
- res.redirect(req.app_context + '/edit/' + newId);
- }
- });
- }
- });
+ var db = req.app.db;
+ var lunr_index = req.app.index;
+
+ var doc = {
+ kb_permalink: req.body.frm_kb_permalink,
+ kb_title: req.body.frm_kb_title,
+ kb_body: req.body.frm_kb_body,
+ kb_published: req.body.frm_kb_published,
+ kb_keywords: req.body.frm_kb_keywords,
+ kb_published_date: new Date(),
+ kb_last_updated: new Date(),
+ kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
+ kb_author: req.session.users_name,
+ kb_author_email: req.session.user
+ };
+
+ db.kb.count({'kb_permalink': req.body.frm_kb_permalink}, function (err, kb){
+ if(kb > 0 && req.body.frm_kb_permalink !== ''){
+ // permalink exits
+ req.session.message = req.i18n.__('Permalink already exists. Pick a new one.');
+ req.session.message_type = 'danger';
+
+ // keep the current stuff
+ req.session.kb_title = req.body.frm_kb_title;
+ req.session.kb_body = req.body.frm_kb_body;
+ req.session.kb_keywords = req.body.frm_kb_keywords;
+ req.session.kb_permalink = req.body.frm_kb_permalink;
+
+ // redirect to insert
+ res.redirect(req.app_context + '/insert');
+ }else{
+ db.kb.insert(doc, function (err, newDoc){
+ if(err){
+ console.error('Error inserting document: ' + err);
+
+ // keep the current stuff
+ req.session.kb_title = req.body.frm_kb_title;
+ req.session.kb_body = req.body.frm_kb_body;
+ req.session.kb_keywords = req.body.frm_kb_keywords;
+ req.session.kb_permalink = req.body.frm_kb_permalink;
+
+ req.session.message = req.i18n.__('Error') + ': ' + err;
+ req.session.message_type = 'danger';
+
+ // redirect to insert
+ res.redirect(req.app_context + '/insert');
+ }else{
+ // setup keywords
+ var keywords = '';
+ if(req.body.frm_kb_keywords !== undefined){
+ keywords = req.body.frm_kb_keywords.toString().replace(/,/g, ' ');
+ }
+
+ // get the new ID
+ var newId = newDoc._id;
+ if(config.settings.database.type !== 'embedded'){
+ newId = newDoc.insertedIds[0];
+ }
+
+ // create lunr doc
+ var lunr_doc = {
+ kb_title: req.body.frm_kb_title,
+ kb_keywords: keywords,
+ id: newId
+ };
+
+ console.log('lunr_doc', lunr_doc);
+
+ // if index body is switched on
+ if(config.settings.index_article_body === true){
+ lunr_doc['kb_body'] = req.body.frm_kb_body;
+ }
+
+ // add to lunr index
+ lunr_index.add(lunr_doc);
+
+ req.session.message = req.i18n.__('New article successfully created');
+ req.session.message_type = 'success';
+
+ // redirect to new doc
+ res.redirect(req.app_context + '/edit/' + newId);
+ }
+ });
+ }
+ });
});
-// Update an existing KB article form action
+// Suggest a new article
router.get('/suggest', common.suggest_allowed, function (req, res){
- // set the template dir
- common.setTemplateDir('admin', req);
-
- res.render('suggest', {
- title: 'Suggest article',
- config: config,
- editor: true,
- is_admin: req.session.is_admin,
- helpers: req.handlebars,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- session: req.session
- });
+ // set the template dir
+ common.setTemplateDir('admin', req);
+
+ res.render('suggest', {
+ title: 'Suggest article',
+ config: config,
+ editor: true,
+ is_admin: req.session.is_admin,
+ helpers: req.handlebars,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ session: req.session
+ });
});
// Update an existing KB article form action
router.post('/insert_suggest', common.suggest_allowed, function (req, res){
- var db = req.app.db;
- var lunr_index = req.app.index;
-
- // if empty, remove the comma and just have a blank string
- var keywords = req.body.frm_kb_keywords.replace(/<(?:.|\n)*?>/gm, '');;
- if(common.safe_trim(keywords) === ','){
- keywords = '';
- }
-
- var doc = {
- kb_title: req.body.frm_kb_title + ' (SUGGESTION)',
- kb_body: req.body.frm_kb_body,
- kb_published: 'false',
- kb_keywords: keywords,
- kb_published_date: new Date(),
- kb_last_updated: new Date()
- };
-
- db.kb.insert(doc, function (err, newDoc){
- if(err){
- console.error('Error inserting suggestion: ' + err);
- req.session.message = req.i18n.__('Suggestion failed. Please contact admin.');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/');
- }else{
- // get the new ID
- var newId = newDoc._id;
- if(config.settings.database.type !== 'embedded'){
- newId = newDoc.insertedIds[0];
- }
-
- // create lunr doc
- var lunr_doc = {
- kb_title: req.body.frm_kb_title,
- kb_keywords: keywords,
- id: newId
- };
-
- // if index body is switched on
- if(config.settings.index_article_body === true){
- lunr_doc['kb_body'] = req.body.frm_kb_body;
- }
-
- // add to lunr index
- lunr_index.add(lunr_doc);
-
- // redirect to new doc
- req.session.message = req.i18n.__('Suggestion successfully processed');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/');
- }
- });
+ var db = req.app.db;
+ var lunr_index = req.app.index;
+
+ // if empty, remove the comma and just have a blank string
+ var keywords = req.body.frm_kb_keywords.replace(/<(?:.|\n)*?>/gm, '');;
+ if(common.safe_trim(keywords) === ','){
+ keywords = '';
+ }
+
+ var doc = {
+ kb_title: req.body.frm_kb_title + ' (SUGGESTION)',
+ kb_body: req.body.frm_kb_body,
+ kb_published: 'false',
+ kb_keywords: keywords,
+ kb_published_date: new Date(),
+ kb_last_updated: new Date()
+ };
+
+ db.kb.insert(doc, function (err, newDoc){
+ if(err){
+ console.error('Error inserting suggestion: ' + err);
+ req.session.message = req.i18n.__('Suggestion failed. Please contact admin.');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/');
+ }else{
+ // get the new ID
+ var newId = newDoc._id;
+ if(config.settings.database.type !== 'embedded'){
+ newId = newDoc.insertedIds[0];
+ }
+
+ // create lunr doc
+ var lunr_doc = {
+ kb_title: req.body.frm_kb_title,
+ kb_keywords: keywords,
+ id: newId
+ };
+
+ // if index body is switched on
+ if(config.settings.index_article_body === true){
+ lunr_doc['kb_body'] = req.body.frm_kb_body;
+ }
+
+ // add to lunr index
+ lunr_index.add(lunr_doc);
+
+ // redirect to new doc
+ req.session.message = req.i18n.__('Suggestion successfully processed');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/');
+ }
+ });
});
// Update an existing KB article form action
router.post('/save_kb', common.restrict, function (req, res){
- var db = req.app.db;
- var lunr_index = req.app.index;
- var kb_featured = req.body.frm_kb_featured === 'on' ? 'true' : 'false';
-
- // if empty, remove the comma and just have a blank string
- var keywords = req.body.frm_kb_keywords.replace(/<(?:.|\n)*?>/gm, '');
- if(common.safe_trim(keywords) === ','){
- keywords = '';
- }
-
- db.kb.count({'kb_permalink': req.body.frm_kb_permalink, $not: {_id: common.getId(req.body.frm_kb_id)}, kb_versioned_doc: {$ne: true}}, function (err, kb){
- if(kb > 0 && req.body.frm_kb_permalink !== ''){
- // permalink exits
- req.session.message = req.i18n.__('Permalink already exists. Pick a new one.');
- req.session.message_type = 'danger';
-
- // keep the current stuff
- req.session.kb_title = req.body.frm_kb_title;
- req.session.kb_body = req.body.frm_kb_body;
- req.session.kb_keywords = req.body.frm_kb_keywords;
- req.session.kb_permalink = req.body.frm_kb_permalink;
- req.session.kb_featured = kb_featured;
- req.session.kb_seo_title = req.body.frm_kb_seo_title;
- req.session.kb_seo_description = req.body.frm_kb_seo_description;
- req.session.kb_edit_reason = req.body.frm_kb_edit_reason;
- req.session.kb_visible_state = req.body.frm_kb_visible_state;
-
- // redirect to insert
- res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
- }else{
- db.kb.findOne({_id: common.getId(req.body.frm_kb_id)}, function (err, article){
- // update author if not set
- var author = article.kb_author ? article.kb_author : req.session.users_name;
- var author_email = article.kb_author_email ? article.kb_author_email : req.session.user;
-
- // set published date to now if none exists
- var published_date;
- if(article.kb_published_date == null || article.kb_published_date === undefined){
- published_date = new Date();
- }else{
- published_date = article.kb_published_date;
- }
-
- // update our old doc
- db.kb.update({_id: common.getId(req.body.frm_kb_id)}, {
- $set: {
- kb_title: req.body.frm_kb_title,
- kb_body: req.body.frm_kb_body,
- kb_published: req.body.frm_kb_published,
- kb_keywords: keywords,
- kb_last_updated: new Date(),
- kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
- kb_author: author,
- kb_author_email: author_email,
- kb_published_date: published_date,
- kb_password: req.body.frm_kb_password,
- kb_permalink: req.body.frm_kb_permalink,
- kb_featured: kb_featured,
- kb_seo_title: req.body.frm_kb_seo_title,
- kb_seo_description: req.body.frm_kb_seo_description,
- kb_visible_state: req.body.frm_kb_visible_state
- }
- }, {}, function (err, numReplaced){
- if(err){
- console.error('Failed to save KB: ' + err);
- req.session.message = req.i18n.__('Failed to save. Please try again');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
- }else{
- // setup keywords
- var keywords = '';
- if(req.body.frm_kb_keywords !== undefined){
- keywords = req.body.frm_kb_keywords.toString().replace(/,/g, ' ');
- }
-
- // create lunr doc
- var lunr_doc = {
- kb_title: req.body.frm_kb_title,
- kb_keywords: keywords,
- id: req.body.frm_kb_id
- };
-
- // if index body is switched on
- if(config.settings.index_article_body === true){
- lunr_doc['kb_body'] = req.body.frm_kb_body;
- }
-
- // update the index
- lunr_index.update(lunr_doc, false);
-
- // check if versioning enabled
- var article_versioning = config.settings.article_versioning ? config.settings.article_versioning : false;
-
- // if versions turned on, insert a doc to track versioning
- if(article_versioning === true){
- // version doc
- var version_doc = {
- kb_title: req.body.frm_kb_title,
- kb_parent_id: req.body.frm_kb_id,
- kb_versioned_doc: true,
- kb_edit_reason: req.body.frm_kb_edit_reason,
- kb_body: req.body.frm_kb_body,
- kb_published: false,
- kb_keywords: keywords,
- kb_last_updated: new Date(),
- kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
- kb_author: author,
- kb_author_email: author_email,
- kb_published_date: published_date,
- kb_password: req.body.frm_kb_password,
- kb_permalink: req.body.frm_kb_permalink,
- kb_featured: kb_featured,
- kb_seo_title: req.body.frm_kb_seo_title,
- kb_seo_description: req.body.frm_kb_seo_description
- };
-
- // insert a doc to track versioning
- db.kb.insert(version_doc, function (err, version_doc){
- req.session.message = req.i18n.__('Successfully saved');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
- });
- }else{
- req.session.message = req.i18n.__('Successfully saved');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
- }
- }
- });
- });
- }
- });
+ var db = req.app.db;
+ var lunr_index = req.app.index;
+ var kb_featured = req.body.frm_kb_featured === 'on' ? 'true' : 'false';
+
+ // if empty, remove the comma and just have a blank string
+ var keywords = req.body.frm_kb_keywords.replace(/<(?:.|\n)*?>/gm, '');
+ if(common.safe_trim(keywords) === ','){
+ keywords = '';
+ }
+
+ db.kb.count({'kb_permalink': req.body.frm_kb_permalink, $not: {_id: common.getId(req.body.frm_kb_id)}, kb_versioned_doc: {$ne: true}}, function (err, kb){
+ if(kb > 0 && req.body.frm_kb_permalink !== ''){
+ // permalink exits
+ req.session.message = req.i18n.__('Permalink already exists. Pick a new one.');
+ req.session.message_type = 'danger';
+
+ // keep the current stuff
+ req.session.kb_title = req.body.frm_kb_title;
+ req.session.kb_body = req.body.frm_kb_body;
+ req.session.kb_keywords = req.body.frm_kb_keywords;
+ req.session.kb_permalink = req.body.frm_kb_permalink;
+ req.session.kb_featured = kb_featured;
+ req.session.kb_seo_title = req.body.frm_kb_seo_title;
+ req.session.kb_seo_description = req.body.frm_kb_seo_description;
+ req.session.kb_edit_reason = req.body.frm_kb_edit_reason;
+ req.session.kb_visible_state = req.body.frm_kb_visible_state;
+
+ // redirect to insert
+ res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
+ }else{
+ db.kb.findOne({_id: common.getId(req.body.frm_kb_id)}, function (err, article){
+ // update author if not set
+ var author = article.kb_author ? article.kb_author : req.session.users_name;
+ var author_email = article.kb_author_email ? article.kb_author_email : req.session.user;
+
+ // set published date to now if none exists
+ var published_date;
+ if(article.kb_published_date == null || article.kb_published_date === undefined){
+ published_date = new Date();
+ }else{
+ published_date = article.kb_published_date;
+ }
+
+ // update our old doc
+ db.kb.update({_id: common.getId(req.body.frm_kb_id)}, {
+ $set: {
+ kb_title: req.body.frm_kb_title,
+ kb_body: req.body.frm_kb_body,
+ kb_published: req.body.frm_kb_published,
+ kb_keywords: keywords,
+ kb_last_updated: new Date(),
+ kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
+ kb_author: author,
+ kb_author_email: author_email,
+ kb_published_date: published_date,
+ kb_password: req.body.frm_kb_password,
+ kb_permalink: req.body.frm_kb_permalink,
+ kb_featured: kb_featured,
+ kb_seo_title: req.body.frm_kb_seo_title,
+ kb_seo_description: req.body.frm_kb_seo_description,
+ kb_visible_state: req.body.frm_kb_visible_state
+ }
+ }, {}, function (err, numReplaced){
+ if(err){
+ console.error('Failed to save KB: ' + err);
+ req.session.message = req.i18n.__('Failed to save. Please try again');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
+ }else{
+ // setup keywords
+ var keywords = '';
+ if(req.body.frm_kb_keywords !== undefined){
+ keywords = req.body.frm_kb_keywords.toString().replace(/,/g, ' ');
+ }
+
+ // create lunr doc
+ var lunr_doc = {
+ kb_title: req.body.frm_kb_title,
+ kb_keywords: keywords,
+ id: req.body.frm_kb_id
+ };
+
+ // if index body is switched on
+ if(config.settings.index_article_body === true){
+ lunr_doc['kb_body'] = req.body.frm_kb_body;
+ }
+
+ // update the index
+ lunr_index.update(lunr_doc, false);
+
+ // check if versioning enabled
+ var article_versioning = config.settings.article_versioning ? config.settings.article_versioning : false;
+
+ // if versions turned on, insert a doc to track versioning
+ if(article_versioning === true){
+ // version doc
+ var version_doc = {
+ kb_title: req.body.frm_kb_title,
+ kb_parent_id: req.body.frm_kb_id,
+ kb_versioned_doc: true,
+ kb_edit_reason: req.body.frm_kb_edit_reason,
+ kb_body: req.body.frm_kb_body,
+ kb_published: false,
+ kb_keywords: keywords,
+ kb_last_updated: new Date(),
+ kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
+ kb_author: author,
+ kb_author_email: author_email,
+ kb_published_date: published_date,
+ kb_password: req.body.frm_kb_password,
+ kb_permalink: req.body.frm_kb_permalink,
+ kb_featured: kb_featured,
+ kb_seo_title: req.body.frm_kb_seo_title,
+ kb_seo_description: req.body.frm_kb_seo_description
+ };
+
+ // insert a doc to track versioning
+ db.kb.insert(version_doc, function (err, version_doc){
+ req.session.message = req.i18n.__('Successfully saved');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
+ });
+ }else{
+ req.session.message = req.i18n.__('Successfully saved');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/edit/' + req.body.frm_kb_id);
+ }
+ }
+ });
+ });
+ }
+ });
});
// logout
router.get('/logout', function (req, res){
- req.session.user = null;
- req.session.users_name = null;
- req.session.is_admin = null;
- req.session.pw_validated = null;
- req.session.message = null;
- req.session.message_type = null;
- res.redirect(req.app_context + '/');
+ req.session.user = null;
+ req.session.users_name = null;
+ req.session.is_admin = null;
+ req.session.pw_validated = null;
+ req.session.message = null;
+ req.session.message_type = null;
+ res.redirect(req.app_context + '/');
});
// users
router.get('/users', common.restrict, function (req, res){
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- var db = req.app.db;
- common.dbQuery(db.users, {}, null, null, function (err, users){
- res.render('users', {
- title: 'Users',
- users: users,
- config: config,
- is_admin: req.session.is_admin,
- helpers: req.handlebars,
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type')
- });
- });
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ var db = req.app.db;
+ common.dbQuery(db.users, {}, null, null, function (err, users){
+ res.render('users', {
+ title: 'Users',
+ users: users,
+ config: config,
+ is_admin: req.session.is_admin,
+ helpers: req.handlebars,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type')
+ });
+ });
});
// users
router.get('/user/edit/:id', common.restrict, function (req, res){
- var db = req.app.db;
- db.users.findOne({_id: common.getId(req.params.id)}, function (err, user){
- // if the user we want to edit is not the current logged in user and the current user is not
- // an admin we render an access denied message
- if(user.user_email !== req.session.user && req.session.is_admin === 'false'){
- req.session.message = req.i18n.__('Access denied');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/Users/');
- return;
- }
-
- res.render('user_edit', {
- title: 'User edit',
- user: user,
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- helpers: req.handlebars,
- config: config
- });
- });
+ var db = req.app.db;
+ db.users.findOne({_id: common.getId(req.params.id)}, function (err, user){
+ // if the user we want to edit is not the current logged in user and the current user is not
+ // an admin we render an access denied message
+ if(user.user_email !== req.session.user && req.session.is_admin === 'false'){
+ req.session.message = req.i18n.__('Access denied');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/Users/');
+ return;
+ }
+
+ res.render('user_edit', {
+ title: 'User edit',
+ user: user,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ helpers: req.handlebars,
+ config: config
+ });
+ });
});
// users
router.get('/users/new', common.restrict, function (req, res){
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- res.render('user_new', {
- title: 'User - New',
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config,
- helpers: req.handlebars
- });
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ res.render('user_new', {
+ title: 'User - New',
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ helpers: req.handlebars
+ });
});
// kb list
router.get('/articles', common.restrict, function (req, res){
- var db = req.app.db;
- common.dbQuery(db.kb, {kb_versioned_doc: {$ne: true}}, {kb_published_date: -1}, 10, function (err, articles){
- res.render('articles', {
- title: 'Articles',
- articles: articles,
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config,
- helpers: req.handlebars
- });
- });
+ var db = req.app.db;
+ common.dbQuery(db.kb, {kb_versioned_doc: {$ne: true}}, {kb_published_date: -1}, 10, function (err, articles){
+ res.render('articles', {
+ title: 'Articles',
+ articles: articles,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ helpers: req.handlebars
+ });
+ });
+});
+
+// list articles by tag
+router.get('/tag', common.restrict, function (req, res){
+ var db = req.app.db;
+ common.dbQuery(db.kb, {kb_versioned_doc: {$ne: true}}, {kb_published_date: -1}, 10, function (err, articles){
+ res.render('tags', {
+ title: 'Articles by Tag',
+ articles: articles,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ helpers: req.handlebars
+ });
+ });
});
router.get('/articles/all', common.restrict, function (req, res){
- var db = req.app.db;
- common.dbQuery(db.kb, {kb_versioned_doc: {$ne: true}}, {kb_published_date: -1}, null, function (err, articles){
- res.render('articles', {
- title: 'Articles',
- articles: articles,
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config,
- helpers: req.handlebars
- });
- });
+ var db = req.app.db;
+ common.dbQuery(db.kb, {kb_versioned_doc: {$ne: true}}, {kb_published_date: -1}, null, function (err, articles){
+ res.render('articles', {
+ title: 'Articles',
+ articles: articles,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ helpers: req.handlebars
+ });
+ });
});
router.get('/articles/:tag', function (req, res){
- var db = req.app.db;
- var lunr_index = req.app.index;
-
- // we strip the ID's from the lunr index search
- var lunr_id_array = [];
- lunr_index.search(req.params.tag + '*').forEach(function (id){
- lunr_id_array.push(id.ref);
- });
-
- // we search on the lunr indexes
- common.dbQuery(db.kb, {_id: {$in: lunr_id_array}}, {kb_published_date: -1}, null, function (err, results){
- res.render('articles', {
- title: 'Articles',
- results: results,
- session: req.session,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- search_term: req.params.tag,
- config: config,
- helpers: req.handlebars
- });
- });
+ var db = req.app.db;
+ var lunr_index = req.app.index;
+
+ // we strip the ID's from the lunr index search
+ var lunr_id_array = [];
+ lunr_index.search(req.params.tag + '*').forEach(function (id){
+ lunr_id_array.push(id.ref);
+ });
+
+ // we search on the lunr indexes
+ common.dbQuery(db.kb, {_id: {$in: lunr_id_array}}, {kb_published_date: -1}, null, function (err, results){
+ res.render('articles', {
+ title: 'Articles',
+ results: results,
+ session: req.session,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ search_term: req.params.tag,
+ config: config,
+ helpers: req.handlebars
+ });
+ });
});
// update the published state based on an ajax call from the frontend
router.post('/published_state', common.restrict, function (req, res){
- var db = req.app.db;
- db.kb.update({_id: common.getId(req.body.id)}, {$set: {kb_published: req.body.state}}, {multi: false}, function (err, numReplaced){
- if(err){
- console.error('Failed to update the published state: ' + err);
- res.writeHead(400, {'Content-Type': 'application/text'});
- res.end('Published state not updated');
- }else{
- res.writeHead(200, {'Content-Type': 'application/text'});
- res.end('Published state updated');
- }
- });
+ var db = req.app.db;
+ db.kb.update({_id: common.getId(req.body.id)}, {$set: {kb_published: req.body.state}}, {multi: false}, function (err, numReplaced){
+ if(err){
+ console.error('Failed to update the published state: ' + err);
+ res.writeHead(400, {'Content-Type': 'application/text'});
+ res.end('Published state not updated');
+ }else{
+ res.writeHead(200, {'Content-Type': 'application/text'});
+ res.end('Published state updated');
+ }
+ });
});
// insert a user
router.post('/user_insert', common.restrict, function (req, res){
- var db = req.app.db;
- var bcrypt = req.bcrypt;
- var url = require('url');
-
- // set the account to admin if using the setup form. Eg: First user account
- var url_parts = url.parse(req.header('Referer'));
-
- // check if account being setup from the /setup route.
- // probably not the most elegent code but does the job.
- var is_admin = 'false';
- if(typeof config.settings.app_context !== 'undefined' && config.settings.app_context !== ''){
- if(url_parts.path === '/' + config.settings.app_context + '/setup'){
- is_admin = 'true';
- }
- }else if(url_parts.path === '/setup'){
- is_admin = 'true';
- }
-
- // sets up the document
- var doc = {
- users_name: req.body.users_name,
- user_email: req.body.user_email,
- user_password: bcrypt.hashSync(req.body.user_password),
- is_admin: is_admin
- };
-
- // check for existing user
- db.users.findOne({'user_email': req.body.user_email}, function (err, user){
- if(user){
- // user already exists with that email address
- console.error('Failed to insert user, possibly already exists: ' + err);
- req.session.message = req.i18n.__('A user with that email address already exists');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/users/new');
- }else{
- // email is ok to be used.
- db.users.insert(doc, function (err, doc){
- // show the view
- if(err){
- console.error('Failed to insert user: ' + err);
- req.session.message = req.i18n.__('User exists');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/user/edit/' + doc._id);
- }else{
- req.session.message = req.i18n.__('User account inserted');
- req.session.message_type = 'success';
-
- // if from setup we add user to session and redirect to login.
- // Otherwise we show users screen
- if(url_parts.path === '/setup'){
- req.session.user = req.body.user_email;
- res.redirect(req.app_context + '/login');
- }else{
- res.redirect(req.app_context + '/Users');
- }
- }
- });
- }
- });
+ var db = req.app.db;
+ var bcrypt = req.bcrypt;
+ var url = require('url');
+
+ // set the account to admin if using the setup form. Eg: First user account
+ var url_parts = url.parse(req.header('Referer'));
+
+ // check if account being setup from the /setup route.
+ // probably not the most elegent code but does the job.
+ var is_admin = 'false';
+ if(typeof config.settings.app_context !== 'undefined' && config.settings.app_context !== ''){
+ if(url_parts.path === '/' + config.settings.app_context + '/setup'){
+ is_admin = 'true';
+ }
+ }else if(url_parts.path === '/setup'){
+ is_admin = 'true';
+ }
+
+ // sets up the document
+ var doc = {
+ users_name: req.body.users_name,
+ user_email: req.body.user_email,
+ user_password: bcrypt.hashSync(req.body.user_password),
+ is_admin: is_admin
+ };
+
+ // check for existing user
+ db.users.findOne({'user_email': req.body.user_email}, function (err, user){
+ if(user){
+ // user already exists with that email address
+ console.error('Failed to insert user, possibly already exists: ' + err);
+ req.session.message = req.i18n.__('A user with that email address already exists');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/users/new');
+ }else{
+ // email is ok to be used.
+ db.users.insert(doc, function (err, doc){
+ // show the view
+ if(err){
+ console.error('Failed to insert user: ' + err);
+ req.session.message = req.i18n.__('User exists');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/user/edit/' + doc._id);
+ }else{
+ req.session.message = req.i18n.__('User account inserted');
+ req.session.message_type = 'success';
+
+ // if from setup we add user to session and redirect to login.
+ // Otherwise we show users screen
+ if(url_parts.path === '/setup'){
+ req.session.user = req.body.user_email;
+ res.redirect(req.app_context + '/login');
+ }else{
+ res.redirect(req.app_context + '/Users');
+ }
+ }
+ });
+ }
+ });
});
// update a user
router.post('/user_update', common.restrict, function (req, res){
- var db = req.app.db;
- var bcrypt = req.bcrypt;
- var is_admin = req.body.user_admin === 'on' ? 'true' : 'false';
-
- // get the user we want to update
- db.users.findOne({_id: common.getId(req.body.user_id)}, function (err, user){
- // if the user we want to edit is not the current logged in user and the current user is not
- // an admin we render an access denied message
- if(user.user_email !== req.session.user && req.session.is_admin === 'false'){
- req.session.message = req.i18n.__('Access denied');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/Users/');
- return;
- }
-
- // if editing your own account, retain admin true/false
- if(user.user_email === req.session.user){
- is_admin = user.is_admin;
- }
-
- // create the update doc
- var update_doc = {};
- update_doc.is_admin = is_admin;
- update_doc.users_name = req.body.users_name;
- if(req.body.user_password){
- update_doc.user_password = bcrypt.hashSync(req.body.user_password);
- }
-
- db.users.update({_id: common.getId(req.body.user_id)},
- {
- $set: update_doc
- }, {multi: false}, function (err, numReplaced){
- if(err){
- console.error('Failed updating user: ' + err);
- req.session.message = req.i18n.__('Failed to update user');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/user/edit/' + req.body.user_id);
- }else{
- // show the view
- req.session.message = req.i18n.__('User account updated.');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/user/edit/' + req.body.user_id);
- }
- });
- });
+ var db = req.app.db;
+ var bcrypt = req.bcrypt;
+ var is_admin = req.body.user_admin === 'on' ? 'true' : 'false';
+
+ // get the user we want to update
+ db.users.findOne({_id: common.getId(req.body.user_id)}, function (err, user){
+ // if the user we want to edit is not the current logged in user and the current user is not
+ // an admin we render an access denied message
+ if(user.user_email !== req.session.user && req.session.is_admin === 'false'){
+ req.session.message = req.i18n.__('Access denied');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/Users/');
+ return;
+ }
+
+ // if editing your own account, retain admin true/false
+ if(user.user_email === req.session.user){
+ is_admin = user.is_admin;
+ }
+
+ // create the update doc
+ var update_doc = {};
+ update_doc.is_admin = is_admin;
+ update_doc.users_name = req.body.users_name;
+ if(req.body.user_password){
+ update_doc.user_password = bcrypt.hashSync(req.body.user_password);
+ }
+
+ db.users.update({_id: common.getId(req.body.user_id)},
+ {
+ $set: update_doc
+ }, {multi: false}, function (err, numReplaced){
+ if(err){
+ console.error('Failed updating user: ' + err);
+ req.session.message = req.i18n.__('Failed to update user');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/user/edit/' + req.body.user_id);
+ }else{
+ // show the view
+ req.session.message = req.i18n.__('User account updated.');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/user/edit/' + req.body.user_id);
+ }
+ });
+ });
});
// login form
router.get('/login', function (req, res){
- var db = req.app.db;
- // set the template
- common.setTemplateDir('admin', req);
-
- db.users.count({}, function (err, user_count){
- // we check for a user. If one exists, redirect to login form otherwise setup
- if(user_count > 0){
- // set needs_setup to false as a user exists
- req.session.needs_setup = false;
-
- // set the referring url
- var referringUrl = req.header('Referer');
- if(typeof req.session.refer_url !== 'undefined' && req.session.refer_url !== ''){
- referringUrl = req.session.refer_url;
- }
-
- res.render('login', {
- title: 'Login',
- referring_url: referringUrl,
- config: config,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- show_footer: 'show_footer',
- helpers: req.handlebars
- });
- }else{
- // if there are no users set the "needs_setup" session
- req.session.needs_setup = true;
- res.redirect(req.app_context + '/setup');
- }
- });
+ var db = req.app.db;
+ // set the template
+ common.setTemplateDir('admin', req);
+
+ db.users.count({}, function (err, user_count){
+ // we check for a user. If one exists, redirect to login form otherwise setup
+ if(user_count > 0){
+ // set needs_setup to false as a user exists
+ req.session.needs_setup = false;
+
+ // set the referring url
+ var referringUrl = req.header('Referer');
+ if(typeof req.session.refer_url !== 'undefined' && req.session.refer_url !== ''){
+ referringUrl = req.session.refer_url;
+ }
+
+ res.render('login', {
+ title: 'Login',
+ referring_url: referringUrl,
+ config: config,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ show_footer: 'show_footer',
+ helpers: req.handlebars
+ });
+ }else{
+ // if there are no users set the "needs_setup" session
+ req.session.needs_setup = true;
+ res.redirect(req.app_context + '/setup');
+ }
+ });
});
// setup form is shown when there are no users setup in the DB
router.get('/setup', function (req, res){
- var db = req.app.db;
- db.users.count({}, function (err, user_count){
- // dont allow the user to "re-setup" if a user exists.
- // set needs_setup to false as a user exists
- req.session.needs_setup = false;
- if(user_count === 0){
- res.render('setup', {
- title: 'Setup',
- config: config,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- show_footer: 'show_footer',
- helpers: req.handlebars
- });
- }else{
- res.redirect(req.app_context + '/login');
- }
- });
+ var db = req.app.db;
+ db.users.count({}, function (err, user_count){
+ // dont allow the user to "re-setup" if a user exists.
+ // set needs_setup to false as a user exists
+ req.session.needs_setup = false;
+ if(user_count === 0){
+ res.render('setup', {
+ title: 'Setup',
+ config: config,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ show_footer: 'show_footer',
+ helpers: req.handlebars
+ });
+ }else{
+ res.redirect(req.app_context + '/login');
+ }
+ });
});
// Loops files on the disk, checks for their existance in any KB articles and removes non used files.
router.get('/file_cleanup', common.restrict, function (req, res){
- var db = req.app.db;
- var path = require('path');
- var fs = require('fs');
- var walk = require('walk');
- var walkPath = path.join(appDir, 'public', 'uploads', 'inline_files');
- var walker = walk.walk(walkPath, {followLinks: false});
-
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- walker.on('file', function (root, stat, next){
- var file_name = path.resolve(root, stat.name);
-
- // find posts with the file in question
- common.dbQuery(db.kb, {'kb_body': new RegExp(stat.name)}, null, null, function (err, posts){
- // if the images doesn't exists in any posts then we remove it
- if(posts.length === 0){
- fs.unlinkSync(file_name);
- }
- next();
- });
- });
-
- walker.on('end', function (){
- req.session.message = req.i18n.__('All unused files have been removed');
- req.session.message_type = 'success';
- res.redirect(req.app_context + req.header('Referer'));
- });
+ var db = req.app.db;
+ var path = require('path');
+ var fs = require('fs');
+ var walk = require('walk');
+ var walkPath = path.join(appDir, 'public', 'uploads', 'inline_files');
+ var walker = walk.walk(walkPath, {followLinks: false});
+
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ walker.on('file', function (root, stat, next){
+ var file_name = path.resolve(root, stat.name);
+
+ // find posts with the file in question
+ common.dbQuery(db.kb, {'kb_body': new RegExp(stat.name)}, null, null, function (err, posts){
+ // if the images doesn't exists in any posts then we remove it
+ if(posts.length === 0){
+ fs.unlinkSync(file_name);
+ }
+ next();
+ });
+ });
+
+ walker.on('end', function (){
+ req.session.message = req.i18n.__('All unused files have been removed');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + req.header('Referer'));
+ });
});
// login the user and check the password
router.post('/login_action', function (req, res){
- var db = req.app.db;
- var bcrypt = req.bcrypt;
- var url = require('url');
-
- db.users.findOne({user_email: req.body.email}, function (err, user){
- // check if user exists with that email
- if(user === undefined || user === null){
- req.session.message = req.i18n.__('A user with that email does not exist.');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/login');
- }else{
- // we have a user under that email so we compare the password
- if(bcrypt.compareSync(req.body.password, user.user_password) === true){
- req.session.user = req.body.email;
- req.session.users_name = user.users_name;
- req.session.user_id = user._id.toString();
- req.session.is_admin = user.is_admin;
- if(req.body.frm_referring_url === undefined || req.body.frm_referring_url === ''){
- res.redirect(req.app_context + '/');
- }else{
- var url_parts = url.parse(req.body.frm_referring_url, true);
- if(url_parts.pathname !== '/setup' && url_parts.pathname !== req.app_context + '/login'){
- res.redirect(req.body.frm_referring_url);
- }else{
- res.redirect(req.app_context + '/');
- }
- }
- }else{
- // password is not correct
- req.session.message = req.i18n.__('Access denied. Check password and try again.');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/login');
- }
- }
- });
+ var db = req.app.db;
+ var bcrypt = req.bcrypt;
+ var url = require('url');
+
+ db.users.findOne({user_email: req.body.email}, function (err, user){
+ // check if user exists with that email
+ if(user === undefined || user === null){
+ req.session.message = req.i18n.__('A user with that email does not exist.');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/login');
+ }else{
+ // we have a user under that email so we compare the password
+ if(bcrypt.compareSync(req.body.password, user.user_password) === true){
+ req.session.user = req.body.email;
+ req.session.users_name = user.users_name;
+ req.session.user_id = user._id.toString();
+ req.session.is_admin = user.is_admin;
+ if(req.body.frm_referring_url === undefined || req.body.frm_referring_url === ''){
+ res.redirect(req.app_context + '/');
+ }else{
+ var url_parts = url.parse(req.body.frm_referring_url, true);
+ if(url_parts.pathname !== '/setup' && url_parts.pathname !== req.app_context + '/login'){
+ res.redirect(req.body.frm_referring_url);
+ }else{
+ res.redirect(req.app_context + '/');
+ }
+ }
+ }else{
+ // password is not correct
+ req.session.message = req.i18n.__('Access denied. Check password and try again.');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/login');
+ }
+ }
+ });
});
// delete user
router.get('/user/delete/:id', common.restrict, function (req, res){
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- var db = req.app.db;
- // remove the article
- if(req.session.is_admin === 'true'){
- db.users.remove({_id: common.getId(req.params.id)}, {}, function (err, numRemoved){
- req.session.message = req.i18n.__('User deleted.');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/users');
- });
- }else{
- req.session.message = req.i18n.__('Access denied.');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/users');
- }
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ var db = req.app.db;
+ // remove the article
+ if(req.session.is_admin === 'true'){
+ db.users.remove({_id: common.getId(req.params.id)}, {}, function (err, numRemoved){
+ req.session.message = req.i18n.__('User deleted.');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/users');
+ });
+ }else{
+ req.session.message = req.i18n.__('Access denied.');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/users');
+ }
});
// delete article
router.get('/delete/:id', common.restrict, function (req, res){
- var db = req.app.db;
- var lunr_index = req.app.index;
-
- // remove the article
- db.kb.remove({_id: common.getId(req.params.id)}, {}, function (err, numRemoved){
- // setup keywords
- var keywords = '';
- if(req.body.frm_kb_keywords !== undefined){
- keywords = req.body.frm_kb_keywords.toString().replace(/,/g, ' ');
- }
-
- // create lunr doc
- var lunr_doc = {
- id: req.params.id
- };
-
- // remove from index
- lunr_index.remove(lunr_doc, false);
-
- // redirect home
- req.session.message = req.i18n.__('Article successfully deleted');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/articles');
- });
+ var db = req.app.db;
+ var lunr_index = req.app.index;
+
+ // remove the article
+ db.kb.remove({_id: common.getId(req.params.id)}, {}, function (err, numRemoved){
+ // setup keywords
+ var keywords = '';
+ if(req.body.frm_kb_keywords !== undefined){
+ keywords = req.body.frm_kb_keywords.toString().replace(/,/g, ' ');
+ }
+
+ // create lunr doc
+ var lunr_doc = {
+ id: req.params.id
+ };
+
+ // remove from index
+ lunr_index.remove(lunr_doc, false);
+
+ // redirect home
+ req.session.message = req.i18n.__('Article successfully deleted');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/articles');
+ });
});
var multer_upload = require('multer');
var inline_upload = multer_upload({dest: path.join(appDir, 'public', 'uploads', 'inline_files')});
router.post('/file/upload_file', common.restrict, inline_upload.single('file'), function (req, res, next){
- var fs = require('fs');
-
- if(req.file){
- // check for upload select
- var upload_dir = path.join(appDir, 'public', 'uploads', 'inline_files');
- var relative_upload_dir = req.app_context + '/uploads/inline_files';
-
- var file = req.file;
- var source = fs.createReadStream(file.path);
- var dest = fs.createWriteStream(path.join(upload_dir, file.originalname));
-
- // save the new file
- source.pipe(dest);
- source.on('end', function (){ });
-
- // delete the temp file.
- fs.unlink(file.path, function (err){ });
-
- // uploaded
- res.writeHead(200, {'Content-Type': 'application/json'});
- res.end(JSON.stringify({'filename': relative_upload_dir + '/' + file.originalname}));
- return;
- }
- res.writeHead(500, {'Content-Type': 'application/json'});
- res.end(JSON.stringify({'filename': 'fail'}, null, 3));
- return;
+ var fs = require('fs');
+
+ if(req.file){
+ // check for upload select
+ var upload_dir = path.join(appDir, 'public', 'uploads', 'inline_files');
+ var relative_upload_dir = req.app_context + '/uploads/inline_files';
+
+ var file = req.file;
+ var source = fs.createReadStream(file.path);
+ var dest = fs.createWriteStream(path.join(upload_dir, file.originalname));
+
+ // save the new file
+ source.pipe(dest);
+ source.on('end', function (){ });
+
+ // delete the temp file.
+ fs.unlink(file.path, function (err){ });
+
+ // uploaded
+ res.writeHead(200, {'Content-Type': 'application/json'});
+ res.end(JSON.stringify({'filename': relative_upload_dir + '/' + file.originalname}));
+ return;
+ }
+ res.writeHead(500, {'Content-Type': 'application/json'});
+ res.end(JSON.stringify({'filename': 'fail'}, null, 3));
+ return;
});
router.post('/file/new_dir', common.restrict, function (req, res, next){
- var mkdirp = require('mkdirp');
-
- // if new directory exists
- if(req.body.custom_dir){
- mkdirp(path.join(appDir, 'public', 'uploads', req.body.custom_dir), function (err){
- if(err){
- console.error('Directory creation error: ' + err);
- req.session.message = req.i18n.__('Directory creation error. Please try again');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/files');
- }else{
- req.session.message = req.i18n.__('Directory successfully created');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/files');
- }
- });
- }else{
- req.session.message = req.i18n.__('Please enter a directory name');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/files');
- }
+ var mkdirp = require('mkdirp');
+
+ // if new directory exists
+ if(req.body.custom_dir){
+ mkdirp(path.join(appDir, 'public', 'uploads', req.body.custom_dir), function (err){
+ if(err){
+ console.error('Directory creation error: ' + err);
+ req.session.message = req.i18n.__('Directory creation error. Please try again');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/files');
+ }else{
+ req.session.message = req.i18n.__('Directory successfully created');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/files');
+ }
+ });
+ }else{
+ req.session.message = req.i18n.__('Please enter a directory name');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/files');
+ }
});
// upload the file
var multer = require('multer');
var upload = multer({dest: path.join(appDir, 'public', 'uploads')});
router.post('/file/upload', common.restrict, upload.single('upload_file'), function (req, res, next){
- var fs = require('fs');
-
- if(req.file){
- // check for upload select
- var upload_dir = path.join(appDir, 'public', 'uploads');
- if(req.body.directory !== '/uploads'){
- upload_dir = path.join(appDir, 'public/', req.body.directory);
- }
-
- var file = req.file;
- var source = fs.createReadStream(file.path);
- var dest = fs.createWriteStream(path.join(upload_dir, file.originalname.replace(/ /g, '_')));
-
- // save the new file
- source.pipe(dest);
- source.on('end', function (){ });
-
- // delete the temp file.
- fs.unlink(file.path, function (err){ });
-
- req.session.message = req.i18n.__('File uploaded successfully');
- req.session.message_type = 'success';
- res.redirect(req.app_context + '/files');
- }else{
- req.session.message = req.i18n.__('File upload error. Please select a file.');
- req.session.message_type = 'danger';
- res.redirect(req.app_context + '/files');
- }
+ var fs = require('fs');
+
+ if(req.file){
+ // check for upload select
+ var upload_dir = path.join(appDir, 'public', 'uploads');
+ if(req.body.directory !== '/uploads'){
+ upload_dir = path.join(appDir, 'public/', req.body.directory);
+ }
+
+ var file = req.file;
+ var source = fs.createReadStream(file.path);
+ var dest = fs.createWriteStream(path.join(upload_dir, file.originalname.replace(/ /g, '_')));
+
+ // save the new file
+ source.pipe(dest);
+ source.on('end', function (){ });
+
+ // delete the temp file.
+ fs.unlink(file.path, function (err){ });
+
+ req.session.message = req.i18n.__('File uploaded successfully');
+ req.session.message_type = 'success';
+ res.redirect(req.app_context + '/files');
+ }else{
+ req.session.message = req.i18n.__('File upload error. Please select a file.');
+ req.session.message_type = 'danger';
+ res.redirect(req.app_context + '/files');
+ }
});
// delete a file via ajax request
router.post('/file/delete', common.restrict, function (req, res){
- var fs = require('fs');
-
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.writeHead(400, {'Content-Type': 'application/text'});
- res.end('Access denied');
- return;
- }
-
- req.session.message = null;
- req.session.message_type = null;
-
- fs.unlink('public/' + req.body.img, function (err){
- if(err){
- console.error('File delete error: ' + err);
- res.writeHead(400, {'Content-Type': 'application/text'});
- res.end('Failed to delete file: ' + err);
- }else{
- res.writeHead(200, {'Content-Type': 'application/text'});
- res.end('File deleted successfully');
- }
- });
+ var fs = require('fs');
+
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.writeHead(400, {'Content-Type': 'application/text'});
+ res.end('Access denied');
+ return;
+ }
+
+ req.session.message = null;
+ req.session.message_type = null;
+
+ fs.unlink('public/' + req.body.img, function (err){
+ if(err){
+ console.error('File delete error: ' + err);
+ res.writeHead(400, {'Content-Type': 'application/text'});
+ res.end('Failed to delete file: ' + err);
+ }else{
+ res.writeHead(200, {'Content-Type': 'application/text'});
+ res.end('File deleted successfully');
+ }
+ });
});
router.get('/files', common.restrict, function (req, res){
- var glob = require('glob');
- var fs = require('fs');
-
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- // loop files in /public/uploads/
- glob('public/uploads/**', {nosort: true}, function (er, files){
- // sort array
- files.sort();
-
- // declare the array of objects
- var file_list = [];
- var dir_list = [];
-
- // loop these files
- for(var i = 0; i < files.length; i++){
- if(fs.existsSync(files[i])){
- if(fs.lstatSync(files[i]).isDirectory() === false){
- // declare the file object and set its values
- var file = {
- id: i,
- path: files[i].substring(6)
- };
-
- // push the file object into the array
- file_list.push(file);
- }else{
- var dir = {
- id: i,
- path: files[i].substring(6)
- };
-
- // push the dir object into the array
- dir_list.push(dir);
- }
- }
- }
-
- // render the files route
- res.render('files', {
- title: 'Files',
- files: file_list,
- dirs: dir_list,
- session: req.session,
- config: config,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- helpers: req.handlebars
- });
- });
+ var glob = require('glob');
+ var fs = require('fs');
+
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ // loop files in /public/uploads/
+ glob('public/uploads/**', {nosort: true}, function (er, files){
+ // sort array
+ files.sort();
+
+ // declare the array of objects
+ var file_list = [];
+ var dir_list = [];
+
+ // loop these files
+ for(var i = 0; i < files.length; i++){
+ if(fs.existsSync(files[i])){
+ if(fs.lstatSync(files[i]).isDirectory() === false){
+ // declare the file object and set its values
+ var file = {
+ id: i,
+ path: files[i].substring(6)
+ };
+
+ // push the file object into the array
+ file_list.push(file);
+ }else{
+ var dir = {
+ id: i,
+ path: files[i].substring(6)
+ };
+
+ // push the dir object into the array
+ dir_list.push(dir);
+ }
+ }
+ }
+
+ // render the files route
+ res.render('files', {
+ title: 'Files',
+ files: file_list,
+ dirs: dir_list,
+ session: req.session,
+ config: config,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ helpers: req.handlebars
+ });
+ });
});
// insert form
router.get('/insert', common.restrict, function (req, res){
- res.render('insert', {
- title: 'Insert new',
- session: req.session,
- kb_title: common.clear_session_value(req.session, 'kb_title'),
- kb_body: common.clear_session_value(req.session, 'kb_body'),
- kb_keywords: common.clear_session_value(req.session, 'kb_keywords'),
- kb_permalink: common.clear_session_value(req.session, 'kb_permalink'),
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- editor: true,
- helpers: req.handlebars,
- config: config
- });
+ res.render('insert', {
+ title: 'Insert new',
+ session: req.session,
+ kb_title: common.clear_session_value(req.session, 'kb_title'),
+ kb_body: common.clear_session_value(req.session, 'kb_body'),
+ kb_keywords: common.clear_session_value(req.session, 'kb_keywords'),
+ kb_permalink: common.clear_session_value(req.session, 'kb_permalink'),
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ editor: true,
+ helpers: req.handlebars,
+ config: config
+ });
});
-// redirect home with a null topic
+// show all available topics (keywords)
router.get('/topic', function(req, res){
- res.redirect('/');
+ var db = req.app.db;
+
+
+ //TODO: implement function
+
+
+
+
});
-// search kb's
-router.get(['/search/:tag', '/topic/:tag'], common.restrict, function (req, res){
- var db = req.app.db;
- common.config_expose(req.app);
- var search_term = req.params.tag;
- var lunr_index = req.app.index;
-
- // determine whether its a search or a topic
- var routeType = 'search';
- if(req.path.split('/')[1] === 'topic'){
- routeType = 'topic';
- }
-
- // we strip the ID's from the lunr index search
- var lunr_id_array = [];
- lunr_index.search(search_term).forEach(function (id){
- // if mongoDB we use ObjectID's, else normal string ID's
- if(config.settings.database.type !== 'embedded'){
- lunr_id_array.push(common.getId(id.ref));
- }else{
- lunr_id_array.push(id.ref);
- }
- });
-
- var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
-
- // get sortBy from config, set to 'kb_viewcount' if nothing found
- var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
- var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
- var sortBy = {};
- sortBy[sortByField] = sortByOrder;
-
- // we search on the lunr indexes
- common.dbQuery(db.kb, {_id: {$in: lunr_id_array}, kb_published: 'true', kb_versioned_doc: {$ne: true}}, null, null, function (err, results){
- common.dbQuery(db.kb, {kb_published: 'true', kb_featured: 'true'}, sortBy, featuredCount, function (err, featured_results){
- res.render('index', {
- title: 'Search results: ' + search_term,
- search_results: results,
- user_page: true,
- session: req.session,
- featured_results: featured_results,
- routeType: routeType,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- search_term: search_term,
- config: config,
- helpers: req.handlebars,
- show_footer: 'show_footer'
- });
- });
- });
+// search kb for topic
+router.get('/topic/:tag', common.restrict, function (req, res){
+ var db = req.app.db;
+ common.config_expose(req.app);
+ var search_term = req.params.tag;
+ var lunr_index = req.app.index;
+
+ routeType = 'topic';
+
+ // we strip the ID's from the lunr index search
+ var lunr_id_array = [];
+ lunr_index.search(search_term).forEach(function (id){
+ // if mongoDB we use ObjectID's, else normal string ID's
+ if(config.settings.database.type !== 'embedded'){
+ lunr_id_array.push(common.getId(id.ref));
+ }else{
+ lunr_id_array.push(id.ref);
+ }
+ });
+
+ var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
+
+ // get sortBy from config, set to 'kb_viewcount' if nothing found
+ var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
+ var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
+ var sortBy = {};
+ sortBy[sortByField] = sortByOrder;
+
+
+ //render topic search
+ // make mongo-like query
+ // Use searchString to build rest of regex
+ // -> Note: 'i' for case insensitive
+ var regex = new RegExp(search_term, 'i');
+
+ // Build query, using regex for each searchable field
+ //{_id: {$in: lunr_id_array}, kb_published: 'true', kb_versioned_doc: {$ne: true}, kb_keywords: {$regex : "ToDo"}}
+ var query = {
+ $and: [
+ {
+ "_id": {$in: lunr_id_array},
+ },
+ {
+ kb_published: 'true',
+ },
+ {
+ kb_versioned_doc: {$ne: true},
+ },
+ {
+ kb_keywords: {"$regex": regex},
+ },
+ ]
+ };
+
+ // we search on the lunr indexes
+ common.dbQuery(db.kb, query, null, null, function (err, results){
+ res.render('search', {
+ title: 'Articles with Topic: ' + search_term,
+ search_results: results,
+ user_page: true,
+ session: req.session,
+ routeType: routeType,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ search_term: search_term,
+ config: config,
+ helpers: req.handlebars,
+ show_footer: 'show_footer',
+ kb_keywords: ''
+ });
+ });
+});
+
+// search kb
+router.get('/search/:tag', common.restrict, function (req, res){
+ var db = req.app.db;
+ common.config_expose(req.app);
+ var search_term = req.params.tag;
+ var lunr_index = req.app.index;
+
+ var routeType = 'search';
+
+ // we strip the ID's from the lunr index search
+ var lunr_id_array = [];
+ lunr_index.search(search_term).forEach(function (id){
+ // if mongoDB we use ObjectID's, else normal string ID's
+ if(config.settings.database.type !== 'embedded'){
+ lunr_id_array.push(common.getId(id.ref));
+ }else{
+ lunr_id_array.push(id.ref);
+ }
+ });
+
+ var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
+
+ // get sortBy from config, set to 'kb_viewcount' if nothing found
+ var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
+ var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
+ var sortBy = {};
+ sortBy[sortByField] = sortByOrder;
+
+ //render regular search
+ // we search on the lunr indexes
+ common.dbQuery(db.kb, {_id: {$in: lunr_id_array}, kb_published: 'true', kb_versioned_doc: {$ne: true}}, null, null, function (err, results){
+ common.dbQuery(db.kb, {kb_published: 'true', kb_featured: 'true'}, sortBy, featuredCount, function (err, featured_results){
+ res.render('search', {
+ title: 'Search results: ' + search_term,
+ search_results: results,
+ user_page: true,
+ session: req.session,
+ featured_results: featured_results,
+ routeType: routeType,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ search_term: search_term,
+ config: config,
+ helpers: req.handlebars,
+ show_footer: 'show_footer',
+ kb_keywords: ''
+ });
+ });
+ });
});
// search kb's
router.post('/search', common.restrict, function (req, res){
- var db = req.app.db;
- common.config_expose(req.app);
- var search_term = req.body.frm_search;
- var lunr_index = req.app.index;
-
- // we strip the ID's from the lunr index search
- var lunr_id_array = [];
- lunr_index.search(search_term).forEach(function (id){
- // if mongoDB we use ObjectID's, else normal string ID's
- if(config.settings.database.type !== 'embedded'){
- lunr_id_array.push(common.getId(id.ref));
- }else{
- lunr_id_array.push(id.ref);
- }
- });
-
- var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
-
- // get sortBy from config, set to 'kb_viewcount' if nothing found
- var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
- var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
- var sortBy = {};
- sortBy[sortByField] = sortByOrder;
-
- // we search on the lunr indexes
- common.dbQuery(db.kb, {_id: {$in: lunr_id_array}, kb_published: 'true', kb_versioned_doc: {$ne: true}}, null, null, function (err, results){
- common.dbQuery(db.kb, {kb_published: 'true', kb_featured: 'true'}, sortBy, featuredCount, function (err, featured_results){
- res.render('index', {
- title: 'Search results: ' + search_term,
- search_results: results,
- user_page: true,
- session: req.session,
- search_term: search_term,
- featured_results: featured_results,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config,
- helpers: req.handlebars,
- show_footer: 'show_footer'
- });
- });
- });
+ var db = req.app.db;
+ common.config_expose(req.app);
+ var search_term = req.body.frm_search;
+ var lunr_index = req.app.index;
+
+ // we strip the ID's from the lunr index search
+ var lunr_id_array = [];
+ lunr_index.search(search_term).forEach(function (id){
+ // if mongoDB we use ObjectID's, else normal string ID's
+ if(config.settings.database.type !== 'embedded'){
+ lunr_id_array.push(common.getId(id.ref));
+ }else{
+ lunr_id_array.push(id.ref);
+ }
+ });
+
+ var featuredCount = config.settings.featured_articles_count ? config.settings.featured_articles_count : 4;
+
+ // get sortBy from config, set to 'kb_viewcount' if nothing found
+ var sortByField = typeof config.settings.sort_by.field !== 'undefined' ? config.settings.sort_by.field : 'kb_viewcount';
+ var sortByOrder = typeof config.settings.sort_by.order !== 'undefined' ? config.settings.sort_by.order : -1;
+ var sortBy = {};
+ sortBy[sortByField] = sortByOrder;
+
+ // we search on the lunr indexes
+ common.dbQuery(db.kb, {_id: {$in: lunr_id_array}, kb_published: 'true', kb_versioned_doc: {$ne: true}}, null, null, function (err, results){
+ common.dbQuery(db.kb, {kb_published: 'true', kb_featured: 'true'}, sortBy, featuredCount, function (err, featured_results){
+ res.render('search', {
+ title: 'Search results: ' + search_term,
+ search_results: results,
+ user_page: true,
+ session: req.session,
+ search_term: search_term,
+ featured_results: featured_results,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config,
+ helpers: req.handlebars,
+ show_footer: 'show_footer'
+ });
+ });
+ });
});
// import form
router.get('/import', common.restrict, function (req, res){
- res.render('import', {
- title: 'Import',
- session: req.session,
- helpers: req.handlebars,
- message: common.clear_session_value(req.session, 'message'),
- message_type: common.clear_session_value(req.session, 'message_type'),
- config: config
- });
+ res.render('import', {
+ title: 'Import',
+ session: req.session,
+ helpers: req.handlebars,
+ message: common.clear_session_value(req.session, 'message'),
+ message_type: common.clear_session_value(req.session, 'message_type'),
+ config: config
+ });
});
router.post('/importer', common.restrict, upload.single('import_file'), function (req, res, next){
- var fs = require('fs');
- var path = require('path');
- var zipExtract = require('extract-zip');
- var rimraf = require('rimraf');
- var db = req.app.db;
- var file = req.file;
-
- // check for allowed file type
- var checkMime = _.includes('application/zip', mime.lookup(file.originalname));
- if(checkMime === false){
- // clean up temp file
- fs.unlinkSync(file.path);
-
- // return error
- res.writeHead(400, {'Content-Type': 'application/text'});
- res.end('File type not permitted. Please upload a zip of Markdown documents.');
- return;
- }
-
- // extract our zip
- zipExtract(file.path, {dir: path.join(__dirname, '..', 'public', 'temp', 'import')}, function (err){
- // remove the zip
- fs.unlinkSync(file.path);
-
- // loop extracted files
- fs.readdir(path.join(__dirname, '..', 'public', 'temp', 'import'), (err, files) => {
- files.forEach(file => {
- // check for blank permalink field and set a nice one base on the title of the FAQ
- var fileNoExt = file.replace(/\.[^/.]+$/, '');
- var permalink = getSlug(fileNoExt);
- var faq_body = fs.readFileSync(path.join(__dirname, '..', 'public', 'temp', 'import', file), 'utf-8');
- if(faq_body === ''){
- faq_body = 'FAQ body';
- }
-
- // setup the doc to insert
- var doc = {
- kb_permalink: permalink,
- kb_title: fileNoExt,
- kb_body: faq_body,
- kb_published: 'false',
- kb_keywords: '',
- kb_published_date: new Date(),
- kb_last_updated: new Date(),
- kb_featured: 'false',
- kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
- kb_author: req.session.users_name,
- kb_author_email: req.session.user
- };
-
- // check permalink if it exists
- common.validate_permalink(db, doc, function (err, result){
- // duplicate permalink
- if(!err){
- // insert article
- db.kb.insert(doc, function (err, newDoc){ });
- }
- });
- });
-
- // clean up dir
- rimraf.sync('public/temp/import');
- req.session.message = 'Articles imported successfully';
- req.session.message_type = 'success';
- res.redirect('/import');
- });
- });
+ var fs = require('fs');
+ var path = require('path');
+ var zipExtract = require('extract-zip');
+ var rimraf = require('rimraf');
+ var db = req.app.db;
+ var file = req.file;
+
+ // check for allowed file type
+ var checkMime = _.includes('application/zip', mime.lookup(file.originalname));
+ if(checkMime === false){
+ // clean up temp file
+ fs.unlinkSync(file.path);
+
+ // return error
+ res.writeHead(400, {'Content-Type': 'application/text'});
+ res.end('File type not permitted. Please upload a zip of Markdown documents.');
+ return;
+ }
+
+ // extract our zip
+ zipExtract(file.path, {dir: path.join(__dirname, '..', 'public', 'temp', 'import')}, function (err){
+ // remove the zip
+ fs.unlinkSync(file.path);
+
+ // loop extracted files
+ fs.readdir(path.join(__dirname, '..', 'public', 'temp', 'import'), (err, files) => {
+ files.forEach(file => {
+ // check for blank permalink field and set a nice one base on the title of the FAQ
+ var fileNoExt = file.replace(/\.[^/.]+$/, '');
+ var permalink = getSlug(fileNoExt);
+ var faq_body = fs.readFileSync(path.join(__dirname, '..', 'public', 'temp', 'import', file), 'utf-8');
+ if(faq_body === ''){
+ faq_body = 'FAQ body';
+ }
+
+ // setup the doc to insert
+ var doc = {
+ kb_permalink: permalink,
+ kb_title: fileNoExt,
+ kb_body: faq_body,
+ kb_published: 'false',
+ kb_keywords: '',
+ kb_published_date: new Date(),
+ kb_last_updated: new Date(),
+ kb_featured: 'false',
+ kb_last_update_user: req.session.users_name + ' - ' + req.session.user,
+ kb_author: req.session.users_name,
+ kb_author_email: req.session.user
+ };
+
+ // check permalink if it exists
+ common.validate_permalink(db, doc, function (err, result){
+ // duplicate permalink
+ if(!err){
+ // insert article
+ db.kb.insert(doc, function (err, newDoc){ });
+ }
+ });
+ });
+
+ // clean up dir
+ rimraf.sync('public/temp/import');
+ req.session.message = 'Articles imported successfully';
+ req.session.message_type = 'success';
+ res.redirect('/import');
+ });
+ });
});
// export files into .md files and serve to browser
router.get('/export', common.restrict, function (req, res){
- var db = req.app.db;
- var fs = require('fs');
- var JSZip = require('jszip');
-
- // only allow admin
- if(req.session.is_admin !== 'true'){
- res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
- return;
- }
-
- // dump all articles to .md files. Article title is the file name and body is contents
- common.dbQuery(db.kb, {}, null, null, function (err, results){
- // files are written and added to zip.
- var zip = new JSZip();
- for(var i = 0; i < results.length; i++){
- // add and write file to zip
- zip.file(results[i].kb_title + '.md', results[i].kb_body);
- }
-
- // save the zip and serve to browser
- var buffer = zip.generate({type: 'nodebuffer'});
- fs.writeFile('data/export.zip', buffer, function (err){
- if(err)throw err;
- res.set('Content-Type', 'application/zip');
- res.set('Content-Disposition', 'attachment; filename=data/export.zip');
- res.set('Content-Length', buffer.length);
- res.end(buffer, 'binary');
- return;
- });
- });
+ var db = req.app.db;
+ var fs = require('fs');
+ var JSZip = require('jszip');
+
+ // only allow admin
+ if(req.session.is_admin !== 'true'){
+ res.render('error', {message: 'Access denied', helpers: req.handlebars, config: config});
+ return;
+ }
+
+ // dump all articles to .md files. Article title is the file name and body is contents
+ common.dbQuery(db.kb, {}, null, null, function (err, results){
+ // files are written and added to zip.
+ var zip = new JSZip();
+ for(var i = 0; i < results.length; i++){
+ // add and write file to zip
+ zip.file(results[i].kb_title + '.md', results[i].kb_body);
+ }
+
+ // save the zip and serve to browser
+ var buffer = zip.generate({type: 'nodebuffer'});
+ fs.writeFile('data/export.zip', buffer, function (err){
+ if(err)throw err;
+ res.set('Content-Type', 'application/zip');
+ res.set('Content-Disposition', 'attachment; filename=data/export.zip');
+ res.set('Content-Length', buffer.length);
+ res.end(buffer, 'binary');
+ return;
+ });
+ });
});
// return sitemap
router.get('/sitemap.xml', function (req, res, next){
- var sm = require('sitemap');
- var db = req.app.db;
-
- // get the articles
- common.dbQuery(db.kb, {kb_published: 'true', kb_visible_state: {$ne: 'private'}}, null, null, function (err, articles){
- var urlArray = [];
-
- // push in the base url
- urlArray.push({url: '/', changefreq: 'weekly', priority: 1.0});
-
- // get the article URL's
- for(var key in articles){
- if(Object.prototype.hasOwnProperty.call(articles, key)){
- // check for permalink
- var pageUrl = '/' + config.settings.route_name + '/' + articles[key]._id;
- if(articles[key].kb_permalink !== ''){
- pageUrl = '/' + config.settings.route_name + '/' + articles[key].kb_permalink;
- }
- urlArray.push({url: pageUrl, changefreq: 'weekly', priority: 1.0});
- }
- }
-
- // create the sitemap
- var sitemap = sm.createSitemap({
- hostname: req.protocol + '://' + req.headers.host,
- cacheTime: 600000, // 600 sec - cache purge period
- urls: urlArray
- });
-
- // render the sitemap
- sitemap.toXML(function(err, xml){
- if(err){
- return res.status(500).end();
- }
- res.header('Content-Type', 'application/xml');
- res.send(xml);
- });
- });
+ var sm = require('sitemap');
+ var db = req.app.db;
+
+ // get the articles
+ common.dbQuery(db.kb, {kb_published: 'true', kb_visible_state: {$ne: 'private'}}, null, null, function (err, articles){
+ var urlArray = [];
+
+ // push in the base url
+ urlArray.push({url: '/', changefreq: 'weekly', priority: 1.0});
+
+ // get the article URL's
+ for(var key in articles){
+ if(Object.prototype.hasOwnProperty.call(articles, key)){
+ // check for permalink
+ var pageUrl = '/' + config.settings.route_name + '/' + articles[key]._id;
+ if(articles[key].kb_permalink !== ''){
+ pageUrl = '/' + config.settings.route_name + '/' + articles[key].kb_permalink;
+ }
+ urlArray.push({url: pageUrl, changefreq: 'weekly', priority: 1.0});
+ }
+ }
+
+ // create the sitemap
+ var sitemap = sm.createSitemap({
+ hostname: req.protocol + '://' + req.headers.host,
+ cacheTime: 600000, // 600 sec - cache purge period
+ urls: urlArray
+ });
+
+ // render the sitemap
+ sitemap.toXML(function(err, xml){
+ if(err){
+ return res.status(500).end();
+ }
+ res.header('Content-Type', 'application/xml');
+ res.send(xml);
+ });
+ });
});
module.exports = router;
diff --git a/views/homepage.hbs b/views/homepage.hbs
new file mode 100644
index 00000000..413a5bb7
--- /dev/null
+++ b/views/homepage.hbs
@@ -0,0 +1,120 @@
+