Fix forever edits (#1716)
* Fix forever edits * Refactor edit check on server
This commit is contained in:
		
							parent
							
								
									6918bcb452
								
							
						
					
					
						commit
						66b7352bf0
					
				@ -8,7 +8,8 @@ import {
 | 
				
			|||||||
  COMMENT_DEPTH_LIMIT, COMMENT_TYPE_QUERY,
 | 
					  COMMENT_DEPTH_LIMIT, COMMENT_TYPE_QUERY,
 | 
				
			||||||
  USER_ID, POLL_COST, ADMIN_ITEMS, GLOBAL_SEED,
 | 
					  USER_ID, POLL_COST, ADMIN_ITEMS, GLOBAL_SEED,
 | 
				
			||||||
  NOFOLLOW_LIMIT, UNKNOWN_LINK_REL, SN_ADMIN_IDS,
 | 
					  NOFOLLOW_LIMIT, UNKNOWN_LINK_REL, SN_ADMIN_IDS,
 | 
				
			||||||
  BOOST_MULT
 | 
					  BOOST_MULT,
 | 
				
			||||||
 | 
					  ITEM_EDIT_SECONDS
 | 
				
			||||||
} from '@/lib/constants'
 | 
					} from '@/lib/constants'
 | 
				
			||||||
import { msatsToSats } from '@/lib/format'
 | 
					import { msatsToSats } from '@/lib/format'
 | 
				
			||||||
import { parse } from 'tldts'
 | 
					import { parse } from 'tldts'
 | 
				
			||||||
@ -1350,8 +1351,9 @@ export const updateItem = async (parent, { sub: subName, forward, hash, hmac, ..
 | 
				
			|||||||
    throw new GqlInputError('item is deleted')
 | 
					    throw new GqlInputError('item is deleted')
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // author can edit their own item (except anon)
 | 
					 | 
				
			||||||
  const meId = Number(me?.id ?? USER_ID.anon)
 | 
					  const meId = Number(me?.id ?? USER_ID.anon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // author can edit their own item (except anon)
 | 
				
			||||||
  const authorEdit = !!me && Number(old.userId) === meId
 | 
					  const authorEdit = !!me && Number(old.userId) === meId
 | 
				
			||||||
  // admins can edit special items
 | 
					  // admins can edit special items
 | 
				
			||||||
  const adminEdit = ADMIN_ITEMS.includes(old.id) && SN_ADMIN_IDS.includes(meId)
 | 
					  const adminEdit = ADMIN_ITEMS.includes(old.id) && SN_ADMIN_IDS.includes(meId)
 | 
				
			||||||
@ -1360,9 +1362,9 @@ export const updateItem = async (parent, { sub: subName, forward, hash, hmac, ..
 | 
				
			|||||||
  if (old.invoice?.hash && hash && hmac) {
 | 
					  if (old.invoice?.hash && hash && hmac) {
 | 
				
			||||||
    hmacEdit = old.invoice.hash === hash && verifyHmac(hash, hmac)
 | 
					    hmacEdit = old.invoice.hash === hash && verifyHmac(hash, hmac)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // ownership permission check
 | 
					  // ownership permission check
 | 
				
			||||||
  if (!authorEdit && !adminEdit && !hmacEdit) {
 | 
					  const ownerEdit = authorEdit || adminEdit || hmacEdit
 | 
				
			||||||
 | 
					  if (!ownerEdit) {
 | 
				
			||||||
    throw new GqlInputError('item does not belong to you')
 | 
					    throw new GqlInputError('item does not belong to you')
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1379,12 +1381,11 @@ export const updateItem = async (parent, { sub: subName, forward, hash, hmac, ..
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const user = await models.user.findUnique({ where: { id: meId } })
 | 
					  const user = await models.user.findUnique({ where: { id: meId } })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // prevent update if it's not explicitly allowed, not their bio, not their job and older than 10 minutes
 | 
					  // edits are only allowed for own items within 10 minutes but forever if it's their bio or a job
 | 
				
			||||||
  const myBio = user.bioId === old.id
 | 
					  const myBio = user.bioId === old.id
 | 
				
			||||||
  const timer = Date.now() < datePivot(new Date(old.invoicePaidAt ?? old.createdAt), { minutes: 10 })
 | 
					  const timer = Date.now() < datePivot(new Date(old.invoicePaidAt ?? old.createdAt), { seconds: ITEM_EDIT_SECONDS })
 | 
				
			||||||
 | 
					  const canEdit = (timer && ownerEdit) || myBio || isJob(item)
 | 
				
			||||||
  // timer permission check
 | 
					  if (!canEdit) {
 | 
				
			||||||
  if (!adminEdit && !myBio && !timer && !isJob(item)) {
 | 
					 | 
				
			||||||
    throw new GqlInputError('item can no longer be edited')
 | 
					    throw new GqlInputError('item can no longer be edited')
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
import { useEffect, useState } from 'react'
 | 
					import { useEffect, useState } from 'react'
 | 
				
			||||||
import { datePivot } from '@/lib/time'
 | 
					import { datePivot } from '@/lib/time'
 | 
				
			||||||
import { useMe } from '@/components/me'
 | 
					import { useMe } from '@/components/me'
 | 
				
			||||||
import { USER_ID } from '@/lib/constants'
 | 
					import { ITEM_EDIT_SECONDS, USER_ID } from '@/lib/constants'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function useCanEdit (item) {
 | 
					export default function useCanEdit (item) {
 | 
				
			||||||
  const editThreshold = datePivot(new Date(item.invoice?.confirmedAt ?? item.createdAt), { minutes: 10 })
 | 
					  const editThreshold = datePivot(new Date(item.invoice?.confirmedAt ?? item.createdAt), { seconds: ITEM_EDIT_SECONDS })
 | 
				
			||||||
  const { me } = useMe()
 | 
					  const { me } = useMe()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // deleted items can never be edited and every item has a 10 minute edit window
 | 
					  // deleted items can never be edited and every item has a 10 minute edit window
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,7 @@ export const MAX_POST_TEXT_LENGTH = 100000 // 100k
 | 
				
			|||||||
export const MAX_COMMENT_TEXT_LENGTH = 10000 // 10k
 | 
					export const MAX_COMMENT_TEXT_LENGTH = 10000 // 10k
 | 
				
			||||||
export const MAX_TERRITORY_DESC_LENGTH = 1000 // 1k
 | 
					export const MAX_TERRITORY_DESC_LENGTH = 1000 // 1k
 | 
				
			||||||
export const MAX_POLL_CHOICE_LENGTH = 40
 | 
					export const MAX_POLL_CHOICE_LENGTH = 40
 | 
				
			||||||
 | 
					export const ITEM_EDIT_SECONDS = 600
 | 
				
			||||||
export const ITEM_SPAM_INTERVAL = '10m'
 | 
					export const ITEM_SPAM_INTERVAL = '10m'
 | 
				
			||||||
export const ANON_ITEM_SPAM_INTERVAL = '0'
 | 
					export const ANON_ITEM_SPAM_INTERVAL = '0'
 | 
				
			||||||
export const INV_PENDING_LIMIT = 100
 | 
					export const INV_PENDING_LIMIT = 100
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@ export const defaultCommentSort = (pinned, bio, createdAt) => {
 | 
				
			|||||||
  return 'hot'
 | 
					  return 'hot'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const isJob = item => item.subName !== 'jobs'
 | 
					export const isJob = item => item.subName === 'jobs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// a delete directive preceded by a non word character that isn't a backtick
 | 
					// a delete directive preceded by a non word character that isn't a backtick
 | 
				
			||||||
const deletePattern = /\B@delete\s+in\s+(\d+)\s+(second|minute|hour|day|week|month|year)s?/gi
 | 
					const deletePattern = /\B@delete\s+in\s+(\d+)\s+(second|minute|hour|day|week|month|year)s?/gi
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user