A web application allowing people to create an account, configure a profile, and share a list of URLs on that profile.
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.
 
 
 
 

138 lines
3.6 KiB

// post.js
// Copyright (C) 2021 Digital Telepresence, LLC
// License: Apache-2.0
'use strict';
const striptags = require('striptags');
const slug = require('slug');
const { SiteService } = require('../../lib/site-lib');
const mongoose = require('mongoose');
const ObjectId = mongoose.Types.ObjectId;
const Post = mongoose.model('Post');
class PostService extends SiteService {
constructor (dtp) {
super(dtp, module.exports);
this.populatePost = [
{
path: 'author',
select: '_id username username_lc displayName picture',
},
];
}
async create (author, postDefinition) {
const NOW = new Date();
const post = new Post();
post.created = NOW;
post.author = author._id;
post.title = striptags(postDefinition.title.trim());
post.slug = this.createPostSlug(post._id, post.title);
post.summary = striptags(postDefinition.summary.trim());
post.content = postDefinition.content.trim();
post.status = postDefinition.status || 'draft';
post.flags = {
enableComments: postDefinition.enableComments === 'on',
isFeatured: postDefinition.isFeatured === 'on',
};
await post.save();
return post.toObject();
}
async update (post, postDefinition) {
const NOW = new Date();
const updateOp = {
$set: {
updated: NOW,
},
};
if (postDefinition.title) {
updateOp.$set.title = striptags(postDefinition.title.trim());
updateOp.$set.slug = this.createPostSlug(post._id, updateOp.$set.title);
}
if (postDefinition.slug) {
let postSlug = striptags(slug(postDefinition.slug.trim())).split('-');
while (ObjectId.isValid(postSlug[postSlug.length - 1])) {
postSlug.pop();
}
postSlug = postSlug.splice(0, 4);
postSlug.push(post._id.toString());
updateOp.$set.slug = `${postSlug.join('-')}`;
}
if (postDefinition.summary) {
updateOp.$set.summary = striptags(postDefinition.summary.trim());
}
if (postDefinition.content) {
updateOp.$set.content = postDefinition.content.trim();
}
if (postDefinition.status) {
updateOp.$set.status = striptags(postDefinition.status.trim());
}
updateOp.$set['flags.enableComments'] = postDefinition.enableComments === 'on';
updateOp.$set['flags.isFeatured'] = postDefinition.isFeatured === 'on';
await Post.updateOne(
{ _id: post._id },
updateOp,
{ upsert: true },
);
}
async getPosts (pagination, status = ['published']) {
if (!Array.isArray(status)) {
status = [status];
}
const posts = await Post
.find({ status: { $in: status } })
.sort({ created: -1 })
.skip(pagination.skip)
.limit(pagination.cpp)
.lean();
return posts;
}
async getById (postId) {
const post = await Post
.findById(postId)
.select('+content')
.populate(this.populatePost)
.lean();
return post;
}
async getBySlug (postSlug) {
const slugParts = postSlug.split('-');
const postId = slugParts[slugParts.length - 1];
return this.getById(postId);
}
async deletePost (post) {
this.log.info('deleting post', { postId: post._id });
await Post.deleteOne({ _id: post._id });
}
createPostSlug (postId, postTitle) {
if ((typeof postTitle !== 'string') || (postTitle.length < 1)) {
throw new Error('Invalid input for making a post slug');
}
const postSlug = slug(postTitle.trim().toLowerCase()).split('-').slice(0, 4).join('-');
return `${postSlug}-${postId}`;
}
}
module.exports = {
slug: 'post',
name: 'post',
create: (dtp) => { return new PostService(dtp); },
};