diff options
author | Cheng-Han, Wu | 2016-04-20 18:03:55 +0800 |
---|---|---|
committer | Cheng-Han, Wu | 2016-04-20 18:03:55 +0800 |
commit | 49b51e478fa75b8d5254662de3265edcf8906004 (patch) | |
tree | 3b09213baae129156339b5ad496924f591790e88 /lib/models/note.js | |
parent | e613aeba75aec5ceb4f10ae62881a3635183857d (diff) |
Refactor server with Sequelize ORM, refactor server configs, now will show note status (created or updated) and support docs (note alias)
Diffstat (limited to '')
-rw-r--r-- | lib/models/note.js | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/lib/models/note.js b/lib/models/note.js new file mode 100644 index 00000000..96043b75 --- /dev/null +++ b/lib/models/note.js @@ -0,0 +1,208 @@ +"use strict"; + +// external modules +var fs = require('fs'); +var path = require('path'); +var LZString = require('lz-string'); +var marked = require('marked'); +var cheerio = require('cheerio'); +var shortId = require('shortid'); +var Sequelize = require("sequelize"); +var async = require('async'); + +// core +var config = require("../config.js"); +var logger = require("../logger.js"); + +// permission types +var permissionTypes = ["freely", "editable", "locked", "private"]; + +module.exports = function (sequelize, DataTypes) { + var Note = sequelize.define("Note", { + id: { + type: DataTypes.UUID, + primaryKey: true, + defaultValue: Sequelize.UUIDV4 + }, + shortid: { + type: DataTypes.STRING, + unique: true, + allowNull: false, + defaultValue: shortId.generate + }, + alias: { + type: DataTypes.STRING, + unique: true + }, + permission: { + type: DataTypes.ENUM, + values: permissionTypes + }, + viewcount: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + title: { + type: DataTypes.TEXT + }, + content: { + type: DataTypes.TEXT + }, + lastchangeAt: { + type: DataTypes.DATE + } + }, { + classMethods: { + associate: function (models) { + Note.belongsTo(models.User, { + foreignKey: "ownerId", + as: "owner", + constraints: false + }); + Note.belongsTo(models.User, { + foreignKey: "lastchangeuserId", + as: "lastchangeuser", + constraints: false + }); + }, + checkFileExist: function (filePath) { + try { + return fs.statSync(filePath).isFile(); + } catch (err) { + return false; + } + }, + checkNoteIdValid: function (id) { + var uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + var result = id.match(uuidRegex); + if (result && result.length == 1) + return true; + else + return false; + }, + parseNoteId: function (noteId, callback) { + async.series({ + parseNoteIdByAlias: function (_callback) { + // try to parse note id by alias (e.g. doc) + Note.findOne({ + where: { + alias: noteId + } + }).then(function (note) { + if (note) { + return callback(null, note.id); + } else { + var filePath = path.join(config.docspath, noteId + '.md'); + if (Note.checkFileExist(filePath)) { + Note.create({ + alias: noteId, + owner: null, + permission: 'locked' + }).then(function (note) { + return callback(null, note.id); + }).catch(function (err) { + return _callback(err, null); + }); + } else { + return _callback(null, null); + } + } + }).catch(function (err) { + return _callback(err, null); + }); + }, + parseNoteIdByLZString: function (_callback) { + // try to parse note id by LZString Base64 + try { + var id = LZString.decompressFromBase64(noteId); + if (id && Note.checkNoteIdValid(id)) + return callback(null, id); + else + return _callback(null, null); + } catch (err) { + return _callback(err, null); + } + }, + parseNoteIdByShortId: function (_callback) { + // try to parse note id by shortId + try { + if (shortId.isValid(noteId)) { + Note.findOne({ + where: { + shortid: noteId + } + }).then(function (note) { + if (!note) return _callback(null, null); + return callback(null, note.id); + }).catch(function (err) { + return _callback(err, null); + }); + } else { + return _callback(null, null); + } + } catch (err) { + return _callback(err, null); + } + } + }, function (err, result) { + if (err) { + logger.error(err); + return callback(err, null); + } + return callback(null, null); + }); + }, + parseNoteTitle: function (body) { + var $ = cheerio.load(marked(body)); + var h1s = $("h1"); + var title = ""; + if (h1s.length > 0 && h1s.first().text().split('\n').length == 1) + title = h1s.first().text(); + else + title = "Untitled"; + return title; + }, + decodeTitle: function (title) { + var decodedTitle = LZString.decompressFromBase64(title); + if (decodedTitle) title = decodedTitle; + else title = 'Untitled'; + return title; + }, + generateWebTitle: function (title) { + title = !title || title == "Untitled" ? "HackMD - Collaborative notes" : title + " - HackMD"; + return title; + } + }, + hooks: { + beforeCreate: function (note, options, callback) { + // if no content specified then use default note + if (!note.content) { + var body = null; + var filePath = null; + if (!note.alias) { + filePath = config.defaultnotepath; + } else { + filePath = path.join(config.docspath, note.alias + '.md'); + } + if (Note.checkFileExist(filePath)) { + body = fs.readFileSync(filePath, 'utf8'); + note.title = LZString.compressToBase64(Note.parseNoteTitle(body)); + note.content = LZString.compressToBase64(body); + } + } + // if no permission specified and have owner then give editable permission, else default permission is freely + if (!note.permission) { + if (note.ownerId) { + note.permission = "editable"; + } else { + note.permission = "freely"; + } + } + return callback(null, note); + } + } + }); + + return Note; +};
\ No newline at end of file |