mirror of https://github.com/Requarks/wiki.git
NGPixel
4 years ago
14 changed files with 412 additions and 24 deletions
Split 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 */ |
|||
|
|||
const window = new JSDOM('').window |
|||
const DOMPurify = createDOMPurify(window) |
|||
|
|||
md.use(mdEmoji) |
|||
|
|||
let akismetClient = null |
|||
|
|||
// ------------------------------------
|
|||
// Default Comment Provider
|
|||
// ------------------------------------
|
|||
|
|||
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