mirror of
https://github.com/social-tw/social-tw-website.git
synced 2026-01-08 23:18:05 -05:00
fix: comment report content mismatch (#639)
* fix: include postId with reporting comment * refactor: enforce postId in report to be either empty string or with value * build: pass postId to relay to create report * chore: fix lint * chore: adjust test for new report history schema * refactor: return correct content of comment report * chore: adjust report history with new schema * fix: typo * fix: add test for post report with non-empty postId * chore: fix typo
This commit is contained in:
@@ -40,12 +40,14 @@ export class ReportService extends RelayApiService {
|
||||
async createReport({
|
||||
type,
|
||||
objectId,
|
||||
postId,
|
||||
reason,
|
||||
category,
|
||||
identityNonce,
|
||||
}: {
|
||||
type: ReportType
|
||||
objectId: string
|
||||
postId?: string
|
||||
reason: string
|
||||
category: number
|
||||
identityNonce: number
|
||||
@@ -65,6 +67,7 @@ export class ReportService extends RelayApiService {
|
||||
_reportData: {
|
||||
type,
|
||||
objectId,
|
||||
postId: postId ?? '',
|
||||
reason,
|
||||
category,
|
||||
reportEpoch: Number(epoch),
|
||||
|
||||
@@ -78,6 +78,7 @@ export interface ReportPostData {
|
||||
|
||||
export interface ReportCommentData {
|
||||
commentId: string
|
||||
postId: string
|
||||
epoch?: number
|
||||
epochKey?: string
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import {
|
||||
useUserState,
|
||||
useUserStateTransition,
|
||||
} from '@/features/core'
|
||||
import { useSendNotification } from '@/features/notification/stores/useNotificationStore'
|
||||
import { NotificationType } from '@/types/Notifications'
|
||||
import { ReportType } from '@/types/Report'
|
||||
import { getEpochKeyNonce } from '@/utils/helpers/getEpochKeyNonce'
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useSendNotification } from '@/features/notification/stores/useNotificationStore'
|
||||
import { NotificationType } from '@/types/Notifications'
|
||||
|
||||
export function useReportComment() {
|
||||
const queryClient = useQueryClient()
|
||||
@@ -50,6 +50,7 @@ export function useReportComment() {
|
||||
const { epoch, epochKey } = await reportService.createReport({
|
||||
type: ReportType.COMMENT,
|
||||
objectId: commentId,
|
||||
postId,
|
||||
reason,
|
||||
category,
|
||||
identityNonce,
|
||||
@@ -64,6 +65,7 @@ export function useReportComment() {
|
||||
onMutate: (variables) => {
|
||||
const reportCommentData: ReportCommentData = {
|
||||
commentId: variables.commentId,
|
||||
postId: variables.postId,
|
||||
epoch: undefined,
|
||||
epochKey: undefined,
|
||||
}
|
||||
@@ -86,6 +88,7 @@ export function useReportComment() {
|
||||
if (context?.actionId) {
|
||||
succeedActionById(context.actionId, {
|
||||
commentId: data.commentId,
|
||||
postId: data.postId,
|
||||
epoch: data.epoch,
|
||||
epochKey: data.epochKey,
|
||||
})
|
||||
|
||||
@@ -11,6 +11,7 @@ export interface ReportHistory {
|
||||
reportId: string
|
||||
type: ReportType // 0: Post, 1: Comment
|
||||
objectId: string // PostId or CommentId
|
||||
postId: string // PostId of the reported object, should be empty for post report
|
||||
object: RelayRawPost | RelayRawComment
|
||||
reportorEpochKey: string // Epoch Key of the person who reported
|
||||
reportorClaimedRep?: boolean // TRUE: claimed, FALSE: not claimed
|
||||
|
||||
@@ -304,6 +304,7 @@ export async function relayReport({
|
||||
proof,
|
||||
type,
|
||||
objectId,
|
||||
postId,
|
||||
reportorEpochKey,
|
||||
reason,
|
||||
category,
|
||||
@@ -312,6 +313,7 @@ export async function relayReport({
|
||||
proof: EpochKeyLiteProof
|
||||
type: ReportType
|
||||
objectId: string
|
||||
postId?: string
|
||||
reportorEpochKey: string
|
||||
reason: string
|
||||
category: number
|
||||
@@ -325,6 +327,7 @@ export async function relayReport({
|
||||
_reportData: {
|
||||
type,
|
||||
objectId,
|
||||
postId: postId ?? '',
|
||||
reportorEpochKey,
|
||||
reason,
|
||||
category,
|
||||
|
||||
@@ -147,6 +147,7 @@ const _schema = [
|
||||
['reportId', 'String'],
|
||||
['type', 'Int'],
|
||||
['objectId', 'String'], // PostId or CommentId
|
||||
['postId', 'String'], // PostId of the reported object
|
||||
['reportorEpochKey', 'String'], // Epoch Key of the person who reported
|
||||
{
|
||||
name: 'reportorClaimedRep',
|
||||
|
||||
@@ -40,6 +40,7 @@ export class ReportService {
|
||||
): Promise<ReportHistory> {
|
||||
// 1.a Check if the post / comment exists is not reported already(post status = 1 / comment status = 1)
|
||||
if (reportData.type === ReportType.POST) {
|
||||
if (reportData.postId) throw Errors.INVALID_POST_ID()
|
||||
if (!Validator.isValidNumber(reportData.objectId))
|
||||
throw Errors.INVALID_POST_ID()
|
||||
|
||||
@@ -52,6 +53,7 @@ export class ReportService {
|
||||
throw Errors.POST_REPORTED()
|
||||
reportData.respondentEpochKey = post.epochKey
|
||||
} else if (reportData.type === ReportType.COMMENT) {
|
||||
if (!reportData.postId) throw Errors.MISSING_POST_ID()
|
||||
if (!Validator.isValidNumber(reportData.objectId))
|
||||
throw Errors.INVALID_COMMENT_ID()
|
||||
const comment = await commentService.fetchSingleComment(
|
||||
@@ -92,6 +94,7 @@ export class ReportService {
|
||||
reportId: reportId,
|
||||
type: reportData.type,
|
||||
objectId: reportData.objectId,
|
||||
postId: reportData.postId,
|
||||
reportorEpochKey: reportData.reportorEpochKey,
|
||||
respondentEpochKey: reportData.respondentEpochKey,
|
||||
reason: reportData.reason,
|
||||
@@ -641,10 +644,13 @@ export class ReportService {
|
||||
|
||||
// Fetch the associated object (post or comment)
|
||||
const tableName = report.type == ReportType.POST ? 'Post' : 'Comment'
|
||||
const whereClause: any = {
|
||||
[`${tableName.toLowerCase()}Id`]: report.objectId,
|
||||
}
|
||||
if (report.postId) whereClause.postId = report.postId
|
||||
|
||||
const object = await db.findOne(tableName, {
|
||||
where: {
|
||||
[`${tableName.toLowerCase()}Id`]: report.objectId,
|
||||
},
|
||||
where: whereClause,
|
||||
})
|
||||
|
||||
// Return the report with its associated object
|
||||
|
||||
@@ -159,6 +159,7 @@ export const Errors = {
|
||||
400,
|
||||
'REPORT_OBJECT_TYPE_NOT_EXISTS'
|
||||
),
|
||||
MISSING_POST_ID: createErrorType('Missing postId', 400, 'MISSING_POST_ID'),
|
||||
INVALID_REPORT_STATUS: createErrorType(
|
||||
'Invalid report status',
|
||||
400,
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface ReportHistory {
|
||||
reportId?: string
|
||||
type: number // 0: Post, 1: Comment
|
||||
objectId: string // PostId or CommentId
|
||||
postId: string // PostId of the reported object
|
||||
reportorEpochKey: string // Epoch Key of the person who reported
|
||||
reportorClaimedRep?: boolean // TRUE: claimed, FALSE: not claimed
|
||||
respondentEpochKey?: string // Epoch Key of the person who was reported
|
||||
|
||||
@@ -139,12 +139,45 @@ describe('POST /api/report', function () {
|
||||
await stopServer('report', snapshot, sync, express)
|
||||
})
|
||||
|
||||
it('should fail to create a report on post with non-empty postId', async function () {
|
||||
const postId = '0'
|
||||
const userState = await genUserState(users[0].id, app, prover)
|
||||
const reportData: ReportHistory = {
|
||||
type: ReportType.POST,
|
||||
objectId: postId,
|
||||
postId: postId,
|
||||
reportorEpochKey: 'epochKey1',
|
||||
reason: 'Inappropriate content',
|
||||
category: ReportCategory.SPAM,
|
||||
reportEpoch: sync.calcCurrentEpoch(),
|
||||
}
|
||||
const reputationProof = await userState.genProveReputationProof({
|
||||
epkNonce: nonce,
|
||||
})
|
||||
|
||||
await express
|
||||
.post('/api/report')
|
||||
.set('content-type', 'application/json')
|
||||
.send(
|
||||
stringifyBigInts({
|
||||
_reportData: reportData,
|
||||
publicSignals: reputationProof.publicSignals,
|
||||
proof: reputationProof.proof,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
expect(res).to.have.status(400)
|
||||
expect(res.body.error).to.be.equal('Invalid postId')
|
||||
})
|
||||
})
|
||||
|
||||
it('should create a report and update post status', async function () {
|
||||
const postId = '0'
|
||||
const userState = await genUserState(users[0].id, app, prover)
|
||||
const reportData: ReportHistory = {
|
||||
type: ReportType.POST,
|
||||
objectId: postId,
|
||||
postId: '',
|
||||
reportorEpochKey: 'epochKey1',
|
||||
reason: 'Inappropriate content',
|
||||
category: ReportCategory.SPAM,
|
||||
@@ -196,9 +229,12 @@ describe('POST /api/report', function () {
|
||||
|
||||
it('should fail to create a report with invalid proof', async function () {
|
||||
const userState = await genUserState(users[0].id, app, prover)
|
||||
const commentId = '0'
|
||||
const postId = '0'
|
||||
const reportData: ReportHistory = {
|
||||
type: ReportType.COMMENT,
|
||||
objectId: '0',
|
||||
objectId: commentId,
|
||||
postId: postId,
|
||||
reportorEpochKey: 'epochKey1',
|
||||
reason: 'Spam',
|
||||
category: ReportCategory.SPAM,
|
||||
@@ -227,12 +263,47 @@ describe('POST /api/report', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('should fail to create a report on comment with empty postId', async function () {
|
||||
const userState = await genUserState(users[0].id, app, prover)
|
||||
const commentId = '0'
|
||||
const postId = ''
|
||||
const reportData: ReportHistory = {
|
||||
type: ReportType.COMMENT,
|
||||
objectId: commentId,
|
||||
postId: postId,
|
||||
reportorEpochKey: 'epochKey1',
|
||||
reason: 'Spam',
|
||||
category: ReportCategory.SPAM,
|
||||
reportEpoch: sync.calcCurrentEpoch(),
|
||||
}
|
||||
const reputationProof = await userState.genProveReputationProof({
|
||||
epkNonce: nonce,
|
||||
})
|
||||
|
||||
await express
|
||||
.post('/api/report')
|
||||
.set('content-type', 'application/json')
|
||||
.send(
|
||||
stringifyBigInts({
|
||||
_reportData: reportData,
|
||||
publicSignals: reputationProof.publicSignals,
|
||||
proof: reputationProof.proof,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
expect(res).to.have.status(400)
|
||||
expect(res.body.error).to.be.equal('Missing postId')
|
||||
})
|
||||
})
|
||||
|
||||
it('should create a report and update comment status', async function () {
|
||||
const commentId = '0'
|
||||
const postId = '0'
|
||||
const userState = await genUserState(users[0].id, app, prover)
|
||||
const reportData: ReportHistory = {
|
||||
type: ReportType.COMMENT,
|
||||
objectId: commentId,
|
||||
postId: postId,
|
||||
reportorEpochKey: 'epochKey1',
|
||||
reason: 'Spam',
|
||||
category: ReportCategory.SPAM,
|
||||
@@ -297,6 +368,7 @@ describe('POST /api/report', function () {
|
||||
const reportData: ReportHistory = {
|
||||
type: ReportType.POST,
|
||||
objectId: '0',
|
||||
postId: '',
|
||||
reportorEpochKey: 'epochKey1',
|
||||
reason: 'Inappropriate content',
|
||||
category: ReportCategory.SPAM,
|
||||
@@ -327,6 +399,7 @@ describe('POST /api/report', function () {
|
||||
const reportData: ReportHistory = {
|
||||
type: ReportType.POST,
|
||||
objectId: 'non-existent',
|
||||
postId: '',
|
||||
reportorEpochKey: 'epochKey1',
|
||||
reason: 'Non-existent post',
|
||||
category: ReportCategory.SPAM,
|
||||
|
||||
@@ -56,13 +56,11 @@ describe('Reputation Claim', function () {
|
||||
let repoterUserState: UserState
|
||||
let repoterEpochKey: EpochKeyLiteProof
|
||||
let posterEpochKey: EpochKeyLiteProof
|
||||
let voterEpochKey: EpochKeyLiteProof
|
||||
let attesterId: bigint
|
||||
let reportedEpochKey: bigint
|
||||
let nullifier: BigInt
|
||||
let voter2: IdentityObject
|
||||
let voter2UserState: UserState
|
||||
let voter2EpochKey: EpochKeyLiteProof
|
||||
let nullifier2: BigInt
|
||||
|
||||
const EPOCH_LENGTH = 3000
|
||||
@@ -89,26 +87,6 @@ describe('Reputation Claim', function () {
|
||||
: [newAdjudicator]
|
||||
}
|
||||
|
||||
async function findReportWithNullifier(
|
||||
db: DB,
|
||||
epoch: number,
|
||||
nullifier: string,
|
||||
status: ReportStatus
|
||||
) {
|
||||
const reports = await db.findMany('ReportHistory', {
|
||||
where: {
|
||||
reportEpoch: epoch,
|
||||
status: status,
|
||||
},
|
||||
})
|
||||
|
||||
return reports.find((report) =>
|
||||
report.adjudicatorsNullifier.some(
|
||||
(adj) => adj.nullifier === nullifier
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
before(async function () {
|
||||
this.timeout(6000000)
|
||||
snapshot = await ethers.provider.send('evm_snapshot', [])
|
||||
@@ -127,9 +105,7 @@ describe('Reputation Claim', function () {
|
||||
sync = synchronizer
|
||||
unirep = _unirep
|
||||
|
||||
// poster = await userService.getLoginUser(db, 'poster', undefined)
|
||||
poster = createRandomUserIdentity()
|
||||
const wallet = ethers.Wallet.createRandom()
|
||||
posterUserState = await signUp(poster, {
|
||||
app,
|
||||
db,
|
||||
@@ -142,9 +118,7 @@ describe('Reputation Claim', function () {
|
||||
expect(hasSignedUp).equal(true)
|
||||
console.log('poster register success...')
|
||||
|
||||
// reporter = await userService.getLoginUser(db, 'reporter', undefined)
|
||||
reporter = createRandomUserIdentity()
|
||||
const wallet2 = ethers.Wallet.createRandom()
|
||||
repoterUserState = await signUp(reporter, {
|
||||
app,
|
||||
db,
|
||||
@@ -157,9 +131,7 @@ describe('Reputation Claim', function () {
|
||||
expect(hasSignedUp2).equal(true)
|
||||
console.log('reporter register success...')
|
||||
|
||||
// voter = await userService.getLoginUser(db, 'voter', undefined)
|
||||
voter = createRandomUserIdentity()
|
||||
const wallet3 = ethers.Wallet.createRandom()
|
||||
voterUserState = await signUp(voter, {
|
||||
app,
|
||||
db,
|
||||
@@ -173,7 +145,6 @@ describe('Reputation Claim', function () {
|
||||
console.log('voter register success...')
|
||||
|
||||
voter2 = createRandomUserIdentity()
|
||||
const wallet4 = ethers.Wallet.createRandom()
|
||||
voter2UserState = await signUp(voter2, {
|
||||
app,
|
||||
db,
|
||||
@@ -186,13 +157,10 @@ describe('Reputation Claim', function () {
|
||||
expect(hasSignedUp4).equal(true)
|
||||
console.log('voter2 register success...')
|
||||
|
||||
voter2EpochKey = await voter2UserState.genEpochKeyLiteProof()
|
||||
|
||||
chainId = await unirep.chainid()
|
||||
|
||||
repoterEpochKey = await repoterUserState.genEpochKeyLiteProof()
|
||||
posterEpochKey = await posterUserState.genEpochKeyLiteProof()
|
||||
voterEpochKey = await voterUserState.genEpochKeyLiteProof()
|
||||
|
||||
attesterId = posterUserState.sync.attesterId
|
||||
|
||||
@@ -211,6 +179,7 @@ describe('Reputation Claim', function () {
|
||||
reportId,
|
||||
type: ReportType.POST,
|
||||
objectId: postId,
|
||||
postId: '',
|
||||
reportorEpochKey: repoterEpochKey.epochKey.toString(),
|
||||
respondentEpochKey: posterEpochKey.epochKey.toString(),
|
||||
reason: 'Test reason',
|
||||
@@ -291,6 +260,7 @@ describe('Reputation Claim', function () {
|
||||
reportId: reportId2,
|
||||
type: ReportType.POST,
|
||||
objectId: postId2,
|
||||
postId: '',
|
||||
reportorEpochKey: repoterEpochKey.epochKey.toString(),
|
||||
respondentEpochKey: posterEpochKey.epochKey.toString(),
|
||||
reason: 'Test reason for failed report',
|
||||
|
||||
Reference in New Issue
Block a user