Skip to content

Commit

Permalink
Merge pull request #471 from dappforce/deploy/permission
Browse files Browse the repository at this point in the history
Add permission denied datahub error handling
  • Loading branch information
olehmell authored Nov 10, 2023
2 parents 8e417f1 + b9cc46b commit fe70436
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL=wss://data-hub.subsocial.network/graphql-ws
GH_DATAHUB_MUTATION_URL=https://queue-data-hub.subsocial.network/graphql
GH_DATAHUB_MUTATION_TOKEN=${{ secrets.DATAHUB_MUTATION_TOKEN }}
GH_NEXT_PUBLIC_OFFCHAIN_POSTING_HUBS=1386
GH_NEXT_PUBLIC_OFFCHAIN_POSTING_HUBS=1386,1399
target: runner
tags: |
${{ env.image }}
Expand Down
4 changes: 2 additions & 2 deletions src/components/auth/LoginModal/LoginModalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,15 @@ export const ConnectWalletContent = ({ setCurrentState }: ContentProps) => {
className='pt-0'
menus={[
{
text: 'Connect EVM',
text: 'EVM',
icon: EthIcon,
onClick: () => {
setCurrentState('evm-address-link')
sendEvent('start_link_evm_address')
},
},
{
text: 'Connect Polkadot',
text: 'Polkadot',
icon: PolkadotIcon,
onClick: () => {
setCurrentState('polkadot-connect')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import MenuList from '@/components/MenuList'
import Notice from '@/components/Notice'
import { useSendEvent } from '@/stores/analytics'
import { useMyAccount } from '@/stores/my-account'
import { truncateAddress } from '@/utils/account'
import { ContentProps } from '../types'

export default function LinkedAddressesContent({
evmAddress,
setCurrentState,
}: ContentProps) {
const sendEvent = useSendEvent()
const hasProxyAddress = useMyAccount((state) => !!state.parentProxyAddress)
const parentProxyAddress = useMyAccount((state) => state.parentProxyAddress)

const commonEventProps = { eventSource: 'account_settings_menu' }
const onLinkEvmAddressClick = () => {
Expand All @@ -31,8 +32,10 @@ export default function LinkedAddressesContent({
{
text: (
<span className='flex items-center gap-2'>
<span>Connect EVM</span>
{evmAddress && <Notice size='sm'>Linked</Notice>}
<span>EVM</span>
{evmAddress && (
<Notice size='sm'>{truncateAddress(evmAddress)}</Notice>
)}
</span>
),
icon: EthIcon,
Expand All @@ -41,8 +44,12 @@ export default function LinkedAddressesContent({
{
text: (
<span className='flex items-center gap-2'>
<span>Connect Polkadot</span>
{hasProxyAddress && <Notice size='sm'>Linked</Notice>}
<span>Polkadot</span>
{parentProxyAddress && (
<Notice size='sm'>
{truncateAddress(parentProxyAddress)}
</Notice>
)}
</span>
),
icon: PolkadotIcon,
Expand Down
35 changes: 19 additions & 16 deletions src/components/chats/ChatForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ function showErrorSendingMessageToast(

const errorData = (error as any)?.response?.data?.errors
const isRateLimited = errorData?.name === ERRORS.RATE_LIMIT_EXCEEDED
const isMessagePermissionDenied =
errorData?.name === ERRORS.CREATE_MESSAGE_PERMISSION_DENIED

let title = errorTitle
if (isRateLimited) {
Expand All @@ -435,23 +437,24 @@ function showErrorSendingMessageToast(
showErrorToast(error, title, {
toastConfig: { duration: isRateLimited ? 5000 : Infinity },
getDescription:
message && !isRateLimited
message && !isRateLimited && !isMessagePermissionDenied
? () => 'Click refresh to recover your message and try again'
: undefined,
actionButton: isRateLimited
? undefined
: (t) => (
<Button
size='circle'
variant='transparent'
className='text-lg'
onClick={() => {
toast.dismiss(t.id)
window.location.reload()
}}
>
<IoRefresh />
</Button>
),
actionButton:
isRateLimited || isMessagePermissionDenied
? undefined
: (t) => (
<Button
size='circle'
variant='transparent'
className='text-lg'
onClick={() => {
toast.dismiss(t.id)
window.location.reload()
}}
>
<IoRefresh />
</Button>
),
})
}
8 changes: 6 additions & 2 deletions src/components/chats/ChatItem/ChatItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,13 @@ export default function ChatItem({
>
{(config) => {
const { toggleDisplay, referenceProps } = config || {}
const showChip = messageStatus === 'offChain' && !isMyMessage
return (
<div
className={cx('relative flex flex-col')}
className={cx(
'relative flex flex-col',
!showChip && 'overflow-hidden'
)}
onContextMenu={(e) => {
e.preventDefault()
toggleDisplay?.(e)
Expand All @@ -94,7 +98,7 @@ export default function ChatItem({
{...referenceProps}
id={messageBubbleId}
>
{messageStatus === 'offChain' && !isMyMessage && (
{showChip && (
<div
className={cx(
'absolute right-0 top-0 z-10 -translate-y-1/3 translate-x-1/2 rounded-full bg-background-primary px-2 py-0.5 text-[8px] text-text-on-primary',
Expand Down
10 changes: 6 additions & 4 deletions src/components/chats/ChatList/ChatListSupportingContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,14 @@ export default function ChatListSupportingContent({
useEffect(() => {
if (!isInitialized.current) return

let newLastReadTime: number | null = null
if (unreadMessage.count === 0 && lastMessageTime) {
let newLastReadTime: number | null = unreadMessage.lastMessageTime
if (
unreadMessage.count === 0 &&
lastMessageTime &&
lastMessageTime > unreadMessage.lastMessageTime
) {
newLastReadTime = lastMessageTime
if (!newLastReadTime) return
} else {
newLastReadTime = unreadMessage.lastMessageTime
}

setLastReadTime(newLastReadTime)
Expand Down
2 changes: 2 additions & 0 deletions src/constants/error.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const ERRORS = {
RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
CREATE_MESSAGE_PERMISSION_DENIED: 'CREATE_MESSAGE_PERMISSION_DENIED',
CREATE_CHAT_PERMISSIONS_DENIED: 'CREATE_CHAT_PERMISSIONS_DENIED',
}
17 changes: 16 additions & 1 deletion src/pages/api/datahub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import {
notifyUpdatePostFailedOrRetryStatus,
updatePostData,
} from '@/server/datahub/post'
import { datahubMutationWrapper, RateLimitError } from '@/server/datahub/utils'
import {
CreateChatPermissionDeniedError,
CreateMessagePermissionDeniedError,
datahubMutationWrapper,
RateLimitError,
} from '@/server/datahub/utils'
import { z } from 'zod'

export type DatahubMutationInput =
Expand Down Expand Up @@ -50,6 +55,16 @@ export default handlerWrapper({
errors: err,
} as ApiResponse)
}
if (
err instanceof CreateChatPermissionDeniedError ||
err instanceof CreateMessagePermissionDeniedError
) {
return res.status(401).send({
success: false,
message: err.message,
errors: err,
} as ApiResponse)
}
throw err
}
res.status(200).json({ message: 'OK', success: true })
Expand Down
47 changes: 39 additions & 8 deletions src/server/datahub/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,23 @@ export function datahubMutationWrapper<
return await func(...args)
} catch (err) {
const errors = (err as any)?.response?.errors
if (Array.isArray(errors)) {
const rateLimitError = errors.find(
(e: any) => e?.code === 'TOO_MANY_REQUESTS_PER_TIME_RANGE'
) as any
const rateLimitData = rateLimitError?.payload
if (rateLimitError) {
if (!Array.isArray(errors)) throw err

const errorCodesMap = {
TOO_MANY_REQUESTS_PER_TIME_RANGE: 'TOO_MANY_REQUESTS_PER_TIME_RANGE',
CREATE_POST_PERMISSIONS_DENIED: 'CREATE_POST_PERMISSIONS_DENIED',
CREATE_COMMENT_PERMISSIONS_DENIED: 'CREATE_COMMENT_PERMISSIONS_DENIED',
}
const foundError = errors.find(
(e: any) => errorCodesMap[(e?.code ?? '') as keyof typeof errorCodesMap]
) as any
if (!foundError) {
throw err
}

switch (foundError.code) {
case errorCodesMap.TOO_MANY_REQUESTS_PER_TIME_RANGE:
const rateLimitData = foundError?.payload
const range = Math.max(rateLimitData.msRange / 1000, 1)
const timeLeft = Math.max(rateLimitData.msBeforeNext / 1000, 1)
throw new RateLimitError(
Expand All @@ -43,9 +54,15 @@ export function datahubMutationWrapper<
}${timeLeft > 1 ? ` (${timeLeft} seconds remaining)` : ''}`,
timeLeft
)
}
case errorCodesMap.CREATE_COMMENT_PERMISSIONS_DENIED:
throw new CreateMessagePermissionDeniedError(
'You are not allowed to send a message in this chat'
)
case errorCodesMap.CREATE_POST_PERMISSIONS_DENIED:
throw new CreateChatPermissionDeniedError(
'You are not allowed to create a chat in this hub'
)
}
throw err
}
}
}
Expand All @@ -56,3 +73,17 @@ export class RateLimitError extends Error {
this.name = ERRORS.RATE_LIMIT_EXCEEDED
}
}

export class CreateMessagePermissionDeniedError extends Error {
constructor(message: string) {
super(message)
this.name = ERRORS.CREATE_MESSAGE_PERMISSION_DENIED
}
}

export class CreateChatPermissionDeniedError extends Error {
constructor(message: string) {
super(message)
this.name = ERRORS.CREATE_CHAT_PERMISSIONS_DENIED
}
}
2 changes: 1 addition & 1 deletion src/services/api/moderation/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const useCommitModerationAction = mutationWrapper(
await revalidateChatPage({ chatId: variables.ctxPostId })
} catch {}

if (!getDatahubConfig()) {
if (getDatahubConfig()) {
getPostMetadataQuery.setQueryData(
queryClient,
variables.ctxPostId,
Expand Down

0 comments on commit fe70436

Please sign in to comment.