Personal blog written from scratch using Node.js, Bootstrap, and MySQL. https://jrtechs.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
11 KiB

  1. const mysql = require('mysql');
  2. const sanitizer = require('sanitizer');
  3. const Promise = require('promise');
  4. const crypto = require('crypto');
  5. const qs = require('querystring');
  6. const utils = require('../utils/utils.js');
  7. var con = mysql.createConnection({
  8. host: "localhost",
  9. user: "blog_user",
  10. password: utils.getFileLine('../sql_secret'),
  11. database: "jrtechs_blog"
  12. });
  13. con.connect(function(err) {
  14. if (err) throw err;
  15. });
  16. /**
  17. * Function used to query the database for records
  18. *
  19. * @param sqlStatement
  20. * @returns {Array}
  21. */
  22. var fetch = function(sqlStatement)
  23. {
  24. return new Promise(function(resolve, reject)
  25. {
  26. con.query(sanitizer.sanitize(sqlStatement), function (err, result)
  27. {
  28. if(err)
  29. {
  30. console.log(err);
  31. reject(err);
  32. }
  33. resolve(result);
  34. });
  35. });
  36. };
  37. module.exports=
  38. {
  39. /**
  40. * Function used to use insert statements into the database
  41. *
  42. * Don't worry, the input gets sanitized
  43. *
  44. * @param sqlStatement
  45. * @return the id of the new record - if there is one
  46. */
  47. insert : function(sqlStatement)
  48. {
  49. return new Promise(function(resolve, reject)
  50. {
  51. con.query(sanitizer.sanitize(sqlStatement), function (err, result)
  52. {
  53. if (err)
  54. {
  55. console.log(err);
  56. resolve(0);
  57. }
  58. resolve(result.insertId);
  59. });
  60. })
  61. },
  62. /**
  63. * function which fetches the sql info on a post based on it's sql id
  64. * @param id
  65. * @returns {Array}
  66. */
  67. getPostById: function(id)
  68. {
  69. console.log("select * from posts where post_id='" + id + "' limit 1");
  70. return new Promise(function(resolve, reject)
  71. {
  72. fetch("select * from posts where post_id='" + id + "' limit 1")
  73. .then(function(post)
  74. {
  75. resolve(post[0]);
  76. }).catch(function(error)
  77. {
  78. reject(error);
  79. });
  80. });
  81. },
  82. /**
  83. * Not to be mistaken for getPostData() in @file utils/utils.js,
  84. * this function extracts a post entry from the sql server
  85. *
  86. * @param requestURL url user used to request blog post
  87. * @return {*} the entry found in the data base -- if any
  88. */
  89. getPost : function(requestURL)
  90. {
  91. return new Promise(function(resolve, reject)
  92. {
  93. var splitURL = requestURL.split("/")
  94. var q = "select * from categories where url='" + splitURL[1] + "'";
  95. fetch(q).then(function (result_category)
  96. {
  97. if(result_category.length != 0)
  98. {
  99. var q2 = "select * from posts where category_id='" +
  100. result_category[0].category_id +
  101. "' and url='" + splitURL[2] + "'";
  102. fetch(q2).then(function (result_posts)
  103. {
  104. if(result_posts != 0)
  105. {
  106. resolve(result_posts[0]);
  107. }
  108. else
  109. {
  110. resolve(0);
  111. }
  112. });
  113. }
  114. else
  115. {
  116. resolve(0);
  117. }
  118. });
  119. });
  120. },
  121. /**
  122. * Function used to retrieve all categories when making the sidebar
  123. *
  124. * @return {Promise<Response> | * | Array}
  125. */
  126. getCategories : function()
  127. {
  128. var q = "select * from categories";
  129. return fetch(q);
  130. },
  131. /**
  132. * Function which currently returns all posts of a particular
  133. * category from the database
  134. * @param requestURL
  135. * @return {*|Promise}
  136. */
  137. getPostsFromCategory: function(requestURL)
  138. {
  139. return new Promise(function(resolve, reject)
  140. {
  141. var q = "select * from categories where url ='" + requestURL + "'";
  142. fetch(q).then(function(categories)
  143. {
  144. if(categories.length != 0)
  145. {
  146. var qPosts = "select * from posts where category_id='" +
  147. categories[0].category_id + "' order by published desc";
  148. resolve(fetch(qPosts));
  149. }
  150. else
  151. {
  152. resolve([]);
  153. }
  154. });
  155. });
  156. },
  157. /**
  158. * Fetches the recent posts from the database.
  159. * @returns {Array}
  160. */
  161. getRecentPostSQL: function()
  162. {
  163. return fetch("select * from posts order by post_id desc limit 10");
  164. },
  165. /**
  166. * Helper method which returns a list of objects which contains the url
  167. * and name of thee ten most recent posts
  168. *
  169. * {[name: , url: ],[name: , url: ],[name: , url: ],...}
  170. *
  171. * @return {*|Promise}
  172. */
  173. getRecentPosts: function()
  174. {
  175. return new Promise(function(resolve, reject)
  176. {
  177. var q = "select name,url, category_id from posts order " +
  178. "by post_id desc limit 10";
  179. fetch(q).then(function(sqlPosts)
  180. {
  181. var promises = [];
  182. sqlPosts.forEach(function(post)
  183. {
  184. promises.push(new Promise(function(res, rej)
  185. {
  186. var getCategory = "select url from categories where " +
  187. "category_id='" + post.category_id + "'";
  188. fetch(getCategory).then(function(urls)
  189. {
  190. var obj = new Object();
  191. obj.name = post.name;
  192. obj.url = post.url;
  193. obj.category = urls[0].url;
  194. res(obj);
  195. });
  196. }));
  197. });
  198. Promise.all(promises).then(function(goodies)
  199. {
  200. resolve(goodies);
  201. });
  202. });
  203. });
  204. },
  205. /**
  206. * TODO
  207. * @returns {*|Promise}
  208. */
  209. getPopularPosts: function()
  210. {
  211. return new Promise(function(resolve, reject)
  212. {
  213. var q = "select * from popular_posts";
  214. fetch(q).then(function(sqlPosts)
  215. {
  216. });
  217. });
  218. },
  219. /**
  220. * Function which checks to see if a user successfully logged in based on
  221. * the post data which they sent
  222. *
  223. * @param postData the post data
  224. * @return {*|Promise} a json object with {pass: , user: }
  225. * the pass is whether or not they logged in successfully and the user is
  226. * the username they successfully logged in with
  227. */
  228. checkLogin: function(postData)
  229. {
  230. var post = qs.parse(postData);
  231. return new Promise(function(resolve, reject)
  232. {
  233. var result = Object();
  234. result.pass = false;
  235. if(post.username && post.password)
  236. {
  237. var cleanName = sanitizer.sanitize(post.username);
  238. var cleanPassword = sanitizer.sanitize(post.password);
  239. var getSalt = "select * from users where user_name='" +
  240. cleanName + "'";
  241. fetch(getSalt).then(function(saltResult)
  242. {
  243. if(saltResult.length == 1)
  244. {
  245. var hashedPassword = crypto.createHash('sha256')
  246. .update(cleanPassword + saltResult[0].salt)
  247. .digest('hex');
  248. if(saltResult[0].password === hashedPassword)
  249. {
  250. result.pass = true;
  251. result.user = cleanName;
  252. resolve(result);
  253. }
  254. else
  255. {
  256. resolve(result)
  257. }
  258. }
  259. else
  260. {
  261. //incorrect username
  262. resolve(result);
  263. }
  264. })
  265. }
  266. else
  267. {
  268. //no login attempts were made
  269. resolve(result);
  270. }
  271. });
  272. },
  273. /**
  274. * Fetches a promise containing every post in the database
  275. * @returns {Array}
  276. */
  277. getAllPosts: function()
  278. {
  279. return fetch("select * from posts order by published desc");
  280. },
  281. /**
  282. * Fetches the sql category information based on it's id
  283. * @param categoryId
  284. * @returns {Array}
  285. */
  286. getCategory: function(categoryId)
  287. {
  288. return fetch("select * from categories where category_id='"
  289. + categoryId + "'");
  290. },
  291. /**TODO work on website downloads
  292. *
  293. * @param downloadURL
  294. * @returns {Array}
  295. */
  296. getDownload: function(downloadURL)
  297. {
  298. var cleanD = sanitizer.sanitize(downloadURL);
  299. var q = "select * from downloads where url='" + cleanD + "' limit 1";
  300. return fetch(q);
  301. },
  302. /**
  303. * Based on the post data submitted by the user this function updates
  304. * the information on the post in the database
  305. * @param postData
  306. * @returns {*|the}
  307. */
  308. editPost: function(postData)
  309. {
  310. var url = postData.edit_name_new.split(" ").join("-").toLowerCase();
  311. var q = "update posts ";
  312. q+= "set category_id='" + postData.edit_cat_num + "' ";
  313. q+= ",name='" + postData.edit_name_new + "' ";
  314. q+= ",url='" + url + "' ";
  315. q+= ",picture_url='" + postData.edit_pic + "' ";
  316. q+= ",published='" + postData.edit_date + "' ";
  317. q+= " where post_id='" + postData.edit_post_2 + "'";
  318. return module.exports.insert(q);
  319. },
  320. /**
  321. * Function which returns a promise which contains the string of the
  322. * entire sitemap for the blog.
  323. * @returns {Promise|*}
  324. */
  325. getSiteMap: function()
  326. {
  327. return new Promise(function(resolve, reject)
  328. {
  329. var base = "http://jrtechs.net/";
  330. var sm = base + "\n";
  331. var promises = [];
  332. module.exports.getCategories().then(function(categories)
  333. {
  334. categories.forEach(function(cat)
  335. {
  336. promises.push(new Promise(function(res, rej)
  337. {
  338. sm += base + "category/" + cat.url + "\n";
  339. module.exports.getPostsFromCategory(cat.url).then(function(posts)
  340. {
  341. posts.forEach(function(post)
  342. {
  343. sm += base + cat.url + "/" + post.url + "\n";
  344. });
  345. res()
  346. })
  347. }));
  348. });
  349. Promise.all(promises).then(function()
  350. {
  351. resolve(sm);
  352. }).catch(function(error)
  353. {
  354. throw error;
  355. });
  356. });
  357. });
  358. }
  359. };