[next] Comment Editing (#1795)

* feat: initial impl of comment edits

* feat: added edit metadata

* review: switched out explcit null + nullable types

* fix: changed commentEdge -> edge, test comments

* [next] Tasks (#1777)

* feat: initial support for synced tenants

* fix: cleanup

* fix: logger now respects logging level

* fix: cache now ignores updates issued from itself

* feat: print subscriber count

* feat: initial moderation + validation for new comments

* fix: added Promiseable type

* feat: initial actions impl

* feat: more moderation phases

* fix: handle settings inheritence

* fix: moved settings into new file

* fix: defaults and documentation

* fix: replace merge with object spread

* feat: added integration with akismet

* fix: support tenant cache for oidc strategy

* fix: fixed compile

* fix: import ordering

* feat: added bull for queue support

* feat: support for scraping

* fix: fixes for scraper

- Implemented simple metascraper replacement (to resolve security advisory
  warning)
- Implemented simle dotize replacement (to resolve not
  working version that couldn't handle date objects)
- Plugged in asset scraping to asset creation process

* fix: handles array values

* feat: added initial scraper implementation

* feat: seperate queues but share config

* fix: simplified auth data access

* feat: moved more settings into the graph

* feat: improved mailer design

* fix: fixed issue with dotize

* fix: fixed some issues with adapter

* fix: queue cleanup

* feat: added organizationName to Tenant

* feat: email rendering

* review: support es6 imports

* fix: restore old ci step

* fix: adjusted logging messages

* fix: linting
This commit is contained in:
Wyatt Johnson
2018-09-04 18:57:41 +00:00
committed by GitHub
parent 59cf728681
commit 3897b06029
15 changed files with 289 additions and 30 deletions
+92 -1
View File
@@ -101,6 +101,97 @@ export async function createComment(
return comment;
}
export type EditCommentInput = Pick<
Comment,
"id" | "author_id" | "body" | "status"
> & {
/**
* lastEditableCommentCreatedAt is the date that the last comment would have
* been editable. It is generally derived from the tenant's
* `editCommentWindowLength` property.
*/
lastEditableCommentCreatedAt: Date;
};
export async function editComment(
db: Db,
tenantID: string,
input: EditCommentInput
) {
const EDITABLE_STATUSES = [
GQLCOMMENT_STATUS.NONE,
GQLCOMMENT_STATUS.PREMOD,
GQLCOMMENT_STATUS.ACCEPTED,
];
const createdAt = new Date();
const { id, body, lastEditableCommentCreatedAt, status, author_id } = input;
const result = await collection(db).findOneAndUpdate(
{
id,
tenant_id: tenantID,
author_id,
status: {
$in: EDITABLE_STATUSES,
},
deleted_at: null,
created_at: {
$gt: lastEditableCommentCreatedAt,
},
},
{
$set: {
body,
status,
},
$push: {
body_history: {
body,
created_at: createdAt,
},
status_history: {
type: status,
created_at: createdAt,
},
},
},
// False to return the updated document instead of the original
// document.
{ returnOriginal: false }
);
if (!result.value) {
// Try to get the comment.
const comment = await retrieveComment(db, tenantID, id);
if (!comment) {
// TODO: (wyattjoh) return better error
throw new Error("comment not found");
}
if (comment.author_id !== author_id) {
// TODO: (wyattjoh) return better error
throw new Error("comment author mismatch");
}
// Check to see if the comment had a status that was editable.
if (!EDITABLE_STATUSES.includes(comment.status)) {
// TODO: (wyattjoh) return better error
throw new Error("comment status is not editable");
}
// Check to see if the edit window expired.
if (comment.created_at <= lastEditableCommentCreatedAt) {
// TODO: (wyattjoh) return better error
throw new Error("edit window expired");
}
// TODO: (wyattjoh) return better error
throw new Error("comment edit failed for an unexpected reason");
}
return result.value;
}
export async function retrieveComment(db: Db, tenantID: string, id: string) {
return collection(db).findOne({ id, tenant_id: tenantID });
}
@@ -129,7 +220,7 @@ export interface ConnectionInput {
}
function cursorGetterFactory(
input: ConnectionInput
input: Pick<ConnectionInput, "orderBy" | "after">
): NodeToCursorTransformer<Comment> {
switch (input.orderBy) {
case GQLCOMMENT_SORT.CREATED_AT_DESC: