212 lines
6.3 KiB
JavaScript
212 lines
6.3 KiB
JavaScript
const { getInstanceSetting } = require('../../models/helpers')
|
|
const Dictionary = require('../../models/dictionary')
|
|
const cache = require('../../models/cache')
|
|
const { promisify } = require('util')
|
|
const email = require('../../models/email')
|
|
|
|
const MIN_ENTRIES_MAIL_NAMESPACE = 'below_min_entries_mail_sent'
|
|
|
|
// Helper object for minEntries below. Defines operations on anti-spam bookmarks.
|
|
const minEntriesEmailBookmark = {
|
|
// Checks whether the anti-spam bookmark (still) exists.
|
|
async exists(dictionaryId) {
|
|
const bookMarkName = `${MIN_ENTRIES_MAIL_NAMESPACE}:${dictionaryId}`
|
|
return !!(await cache.exists(bookMarkName))
|
|
},
|
|
|
|
// Sets the anti-spam bookmark for given dictionary.
|
|
async set(dictionaryId) {
|
|
const bookMarkName = `${MIN_ENTRIES_MAIL_NAMESPACE}:${dictionaryId}`
|
|
await cache.set(bookMarkName, true)
|
|
},
|
|
|
|
// Removes the anti-spam bookmark for given dictionary if conditions are met.
|
|
async update(dictionaryId) {
|
|
const doesBookmarkExist = await this.exists(dictionaryId)
|
|
if (!doesBookmarkExist) return
|
|
const minEntries = await getInstanceSetting('min_entries_per_dictionary')
|
|
const isBelowMinEntriesThreshold = await checkIfBelowMinEntriesThreshold(
|
|
dictionaryId,
|
|
minEntries
|
|
)
|
|
|
|
if (isBelowMinEntriesThreshold) return
|
|
|
|
const bookMarkName = `${MIN_ENTRIES_MAIL_NAMESPACE}:${dictionaryId}`
|
|
await cache.unlink(bookMarkName)
|
|
}
|
|
}
|
|
|
|
// Exports actions related to checking and acting on minimum entries per dictionary setting.
|
|
exports.minEntriesRequirementCheckAndAct = {
|
|
// Checks required criteria and sends notifications emails if required.
|
|
async onDelete(dictionaryId, appRef) {
|
|
const minEntries = await getInstanceSetting('min_entries_per_dictionary')
|
|
|
|
// Only proceed if a valid and positive minimum entries per dictionary setting is set.
|
|
if (!(+minEntries > 0)) return
|
|
|
|
const [isBelowMinEntriesThreshold, wasEmailAlreadySent] = await Promise.all(
|
|
[
|
|
checkIfBelowMinEntriesThreshold(dictionaryId, minEntries),
|
|
minEntriesEmailBookmark.exists(dictionaryId)
|
|
]
|
|
)
|
|
|
|
if (!isBelowMinEntriesThreshold || wasEmailAlreadySent) return
|
|
|
|
// Prepare and send notification emails.
|
|
const [nameSl, adminEmails, dictionariesAdminEmails] = await Promise.all([
|
|
Dictionary.fetchName(dictionaryId),
|
|
Dictionary.fetchAdminEmails(dictionaryId),
|
|
Dictionary.fetchDictionariesAdminEmails()
|
|
])
|
|
|
|
const allEmailsSet = new Set([...adminEmails, ...dictionariesAdminEmails])
|
|
const allEmails = []
|
|
for (const email of allEmailsSet) allEmails.push(email)
|
|
|
|
const type = 'delete'
|
|
const renderAsync = promisify(appRef.render.bind(appRef))
|
|
const emailHtml = await renderAsync('email/dictionary-status-change', {
|
|
type,
|
|
nameSl
|
|
})
|
|
|
|
await email.send({
|
|
to: allEmails,
|
|
subject: 'Obvestilo o številu gesel',
|
|
html: emailHtml
|
|
})
|
|
|
|
await minEntriesEmailBookmark.set(dictionaryId)
|
|
},
|
|
|
|
// Use this method after any entry updating operations to release potential anti-spam bookmarks.
|
|
onUpdate: minEntriesEmailBookmark.update.bind(minEntriesEmailBookmark)
|
|
}
|
|
|
|
// Helper function to check if a given (published) dictionary has less entries than provided minEntries parameter.
|
|
async function checkIfBelowMinEntriesThreshold(dictionaryId, minEntries) {
|
|
const [publishedEntries, dictionaryStatus] = await Promise.all([
|
|
Dictionary.countPublishedEntries(dictionaryId),
|
|
Dictionary.fetchStatus(dictionaryId)
|
|
])
|
|
|
|
const isBelowMinEntriesThreshold =
|
|
+publishedEntries < +minEntries && dictionaryStatus === 'published'
|
|
|
|
return isBelowMinEntriesThreshold
|
|
}
|
|
|
|
// Determine new dictionary status based on dictionary_publish_approval setting.
|
|
exports.determineNewStatus = async isPublished => {
|
|
const publishApproval = await getInstanceSetting(
|
|
'dictionary_publish_approval'
|
|
)
|
|
|
|
let newStatus
|
|
if (publishApproval === 'F') {
|
|
newStatus = isPublished ? 'published' : 'closed'
|
|
} else {
|
|
newStatus = isPublished ? 'reviewed' : 'closed'
|
|
}
|
|
|
|
return newStatus
|
|
}
|
|
|
|
// Exports actions related to checking and acting on dictionary status changes.
|
|
exports.statusChangeCheckAndAct = {
|
|
// Notify dictionaries admins by email on dictionary status changes.
|
|
async updateUsers(
|
|
dictionaryId,
|
|
isPublishedNew,
|
|
oldDictStatus,
|
|
nameSl,
|
|
appRef,
|
|
user
|
|
) {
|
|
const isPublishedOld = oldDictStatus === 'published'
|
|
|
|
// Published: on -> off.
|
|
if (!isPublishedNew && isPublishedOld) {
|
|
const dictionariesAdminEmails =
|
|
await Dictionary.fetchDictionariesAdminEmails()
|
|
const type = 'unpublish'
|
|
|
|
await renderAndSendStatusChangeEmails(
|
|
appRef,
|
|
type,
|
|
user.email,
|
|
nameSl,
|
|
dictionariesAdminEmails
|
|
)
|
|
|
|
// Published: off -> on.
|
|
} else if (isPublishedNew && !isPublishedOld) {
|
|
const [isApprovalRequired, dictionariesAdminEmails] = await Promise.all([
|
|
getInstanceSetting('dictionary_publish_approval'),
|
|
Dictionary.fetchDictionariesAdminEmails()
|
|
])
|
|
const type =
|
|
isApprovalRequired === 'T' ? 'publish-approval' : 'publish-no-approval'
|
|
|
|
await renderAndSendStatusChangeEmails(
|
|
appRef,
|
|
type,
|
|
user.email,
|
|
nameSl,
|
|
dictionariesAdminEmails
|
|
)
|
|
}
|
|
},
|
|
|
|
// Notify dictionary admins by email after dictionaries admins
|
|
// change dictionary status from reviewed to either closed or published.
|
|
async updateAdminDescription(
|
|
dictionaryId,
|
|
statusNew,
|
|
statusOld,
|
|
appRef,
|
|
user
|
|
) {
|
|
if (statusOld === 'reviewed' && statusNew !== 'reviewed') {
|
|
const [nameSl, adminEmails] = await Promise.all([
|
|
Dictionary.fetchName(dictionaryId),
|
|
Dictionary.fetchAdminEmails(dictionaryId)
|
|
])
|
|
const type = 'status'
|
|
|
|
await renderAndSendStatusChangeEmails(
|
|
appRef,
|
|
type,
|
|
user.email,
|
|
nameSl,
|
|
adminEmails
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Helper function used by statusChangeCheckAndAct methods.
|
|
async function renderAndSendStatusChangeEmails(
|
|
appRef,
|
|
type,
|
|
changerEmail,
|
|
nameSl,
|
|
targetEmails
|
|
) {
|
|
const renderAsync = promisify(appRef.render.bind(appRef))
|
|
const emailHtml = await renderAsync('email/dictionary-status-change', {
|
|
type,
|
|
changerEmail,
|
|
nameSl
|
|
})
|
|
|
|
await email.send({
|
|
to: targetEmails,
|
|
subject: 'Sprememba stanja slovarja',
|
|
html: emailHtml
|
|
})
|
|
}
|