mirror of https://github.com/Requarks/wiki.git
14 changed files with 412 additions and 24 deletions
Unified View
Diff Options
-
2client/components/admin/admin-groups-edit-permissions.vue
-
148client/components/comments.vue
-
6client/store/page.js
-
9client/themes/default/components/page.vue
-
1package.json
-
14server/controllers/common.js
-
8server/db/migrations-sqlite/2.4.61.js
-
8server/db/migrations/2.4.61.js
-
25server/graph/resolvers/comment.js
-
6server/graph/schemas/comment.graphql
-
55server/models/comments.js
-
106server/modules/comments/default/comment.js
-
2server/views/page.pug
-
46yarn.lock
@ -0,0 +1,8 @@ |
|||||
|
exports.up = knex => { |
||||
|
return knex.schema |
||||
|
.alterTable('comments', table => { |
||||
|
table.integer('replyTo').unsigned().notNullable().defaultTo(0) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
exports.down = knex => { } |
@ -0,0 +1,8 @@ |
|||||
|
exports.up = knex => { |
||||
|
return knex.schema |
||||
|
.alterTable('comments', table => { |
||||
|
table.integer('replyTo').unsigned().notNullable().defaultTo(0) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
exports.down = knex => { } |
@ -0,0 +1,55 @@ |
|||||
|
const Model = require('objection').Model |
||||
|
|
||||
|
/** |
||||
|
* Comments model |
||||
|
*/ |
||||
|
module.exports = class Comment extends Model { |
||||
|
static get tableName() { return 'comments' } |
||||
|
|
||||
|
static get jsonSchema () { |
||||
|
return { |
||||
|
type: 'object', |
||||
|
required: [], |
||||
|
|
||||
|
properties: { |
||||
|
id: {type: 'integer'}, |
||||
|
content: {type: 'string'}, |
||||
|
render: {type: 'string'}, |
||||
|
name: {type: 'string'}, |
||||
|
email: {type: 'string'}, |
||||
|
ip: {type: 'string'}, |
||||
|
createdAt: {type: 'string'}, |
||||
|
updatedAt: {type: 'string'} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static get relationMappings() { |
||||
|
return { |
||||
|
author: { |
||||
|
relation: Model.BelongsToOneRelation, |
||||
|
modelClass: require('./users'), |
||||
|
join: { |
||||
|
from: 'comments.authorId', |
||||
|
to: 'users.id' |
||||
|
} |
||||
|
}, |
||||
|
page: { |
||||
|
relation: Model.BelongsToOneRelation, |
||||
|
modelClass: require('./pages'), |
||||
|
join: { |
||||
|
from: 'comments.pageId', |
||||
|
to: 'pages.id' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$beforeUpdate() { |
||||
|
this.updatedAt = new Date().toISOString() |
||||
|
} |
||||
|
$beforeInsert() { |
||||
|
this.createdAt = new Date().toISOString() |
||||
|
this.updatedAt = new Date().toISOString() |
||||
|
} |
||||
|
} |
@ -1,11 +1,115 @@ |
|||||
|
const md = require('markdown-it') |
||||
|
const mdEmoji = require('markdown-it-emoji') |
||||
|
const { JSDOM } = require('jsdom') |
||||
|
const createDOMPurify = require('dompurify') |
||||
|
const _ = require('lodash') |
||||
|
const { AkismetClient } = require('akismet-api') |
||||
|
|
||||
/* global WIKI */ |
/* global WIKI */ |
||||
|
|
||||
|
const window = new JSDOM('').window |
||||
|
const DOMPurify = createDOMPurify(window) |
||||
|
|
||||
|
md.use(mdEmoji) |
||||
|
|
||||
|
let akismetClient = null |
||||
|
|
||||
// ------------------------------------
|
// ------------------------------------
|
||||
// Default Comment Provider
|
// Default Comment Provider
|
||||
// ------------------------------------
|
// ------------------------------------
|
||||
|
|
||||
module.exports = { |
module.exports = { |
||||
add (args) { |
|
||||
|
/** |
||||
|
* Init |
||||
|
*/ |
||||
|
async init (config) { |
||||
|
if (WIKI.data.commentProvider.config.akismet && WIKI.data.commentProvider.config.akismet.length > 2) { |
||||
|
akismetClient = new AkismetClient({ |
||||
|
key: WIKI.data.commentProvider.config.akismet, |
||||
|
blog: WIKI.config.host, |
||||
|
lang: WIKI.config.lang.namespacing ? WIKI.config.lang.namespaces.join(', ') : WIKI.config.lang.code, |
||||
|
charset: 'UTF-8' |
||||
|
}) |
||||
|
try { |
||||
|
const isValid = await akismetClient.verifyKey() |
||||
|
if (!isValid) { |
||||
|
WIKI.logger.warn('Akismet Key is invalid!') |
||||
|
} |
||||
|
} catch (err) { |
||||
|
WIKI.logger.warn('Unable to verify Akismet Key: ' + err.message) |
||||
|
} |
||||
|
} else { |
||||
|
akismetClient = null |
||||
|
} |
||||
|
}, |
||||
|
/** |
||||
|
* Create New Comment |
||||
|
*/ |
||||
|
async create ({ page, replyTo, content, user }) { |
||||
|
// -> Render Markdown
|
||||
|
const mkdown = md({ |
||||
|
html: false, |
||||
|
breaks: true, |
||||
|
linkify: true, |
||||
|
highlight(str, lang) { |
||||
|
return `<pre><code class="language-${lang}">${_.escape(str)}</code></pre>` |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// -> Build New Comment
|
||||
|
const newComment = { |
||||
|
content, |
||||
|
render: DOMPurify.sanitize(mkdown.render(content)), |
||||
|
replyTo, |
||||
|
pageId: page.id, |
||||
|
authorId: user.id, |
||||
|
name: user.name, |
||||
|
email: user.email, |
||||
|
ip: user.ip |
||||
|
} |
||||
|
|
||||
|
// Check for Spam with Akismet
|
||||
|
if (akismetClient) { |
||||
|
let userRole = 'user' |
||||
|
if (user.groups.indexOf(1) >= 0) { |
||||
|
userRole = 'administrator' |
||||
|
} else if (user.groups.indexOf(2) >= 0) { |
||||
|
userRole = 'guest' |
||||
|
} |
||||
|
|
||||
|
let isSpam = false |
||||
|
try { |
||||
|
isSpam = await akismetClient.checkSpam({ |
||||
|
ip: user.ip, |
||||
|
useragent: user.agentagent, |
||||
|
content, |
||||
|
name: user.name, |
||||
|
email: user.email, |
||||
|
permalink: `${WIKI.config.host}/${page.localeCode}/${page.path}`, |
||||
|
permalinkDate: page.updatedAt, |
||||
|
type: (replyTo > 0) ? 'reply' : 'comment', |
||||
|
role: userRole |
||||
|
}) |
||||
|
} catch (err) { |
||||
|
WIKI.logger.warn('Akismet Comment Validation: [ FAILED ]') |
||||
|
WIKI.logger.warn(err) |
||||
|
} |
||||
|
|
||||
|
if (isSpam) { |
||||
|
throw new Error('Comment was rejected because it is marked as spam.') |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Save Comment
|
||||
|
await WIKI.models.comments.query().insert(newComment) |
||||
|
}, |
||||
|
async update ({ id, content, user, ip }) { |
||||
|
|
||||
|
}, |
||||
|
async remove ({ id, user, ip }) { |
||||
|
|
||||
|
}, |
||||
|
async count ({ pageId }) { |
||||
|
|
||||
} |
} |
||||
} |
} |
Write
Preview
Loading…
Cancel
Save