Skip to content

Commit

Permalink
Add remove linked identity
Browse files Browse the repository at this point in the history
  • Loading branch information
teodorus-nathaniel committed Jun 19, 2024
1 parent a43fddc commit d05a0a4
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 2 deletions.
27 changes: 27 additions & 0 deletions src/modules/telegram/AirdropPage/RemoveLinkedIdentityModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import ConfirmationModal from '@/components/modals/ConfirmationModal'
import { ModalFunctionalityProps } from '@/components/modals/Modal'
import { useRemoveMyLinkedIdentity } from '@/services/api/mutation'
import { useMyAccount } from '@/stores/my-account'

export default function RemoveLinkedIdentityModal(
props: ModalFunctionalityProps
) {
const { mutate } = useRemoveMyLinkedIdentity({
onSuccess: () => {
useMyAccount.getState().logout()
window.location.reload()
},
})
return (
<ConfirmationModal
{...props}
title='Are you sure to remove this account?'
description='This action cannot be undone'
primaryButtonProps={{
children: 'Yes, remove this account',
onClick: () => mutate(null),
}}
secondaryButtonProps={{ children: 'Cancel', onClick: props.closeModal }}
/>
)
}
23 changes: 21 additions & 2 deletions src/modules/telegram/AirdropPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@ import { CommonEVMLoginContent } from '@/components/auth/common/evm/CommonEvmMod
import LayoutWithBottomNavigation from '@/components/layouts/LayoutWithBottomNavigation'
import Modal, { ModalFunctionalityProps } from '@/components/modals/Modal'
import SubsocialProfileModal from '@/components/subsocial-profile/SubsocialProfileModal'
import useLinkedEvmAddress from '@/hooks/useLinkedEvmAddress'
import useIsModerationAdmin from '@/hooks/useIsModerationAdmin'
import useTgNoScroll from '@/hooks/useTgNoScroll'
import PointsWidget from '@/modules/points/PointsWidget'
import { useSendEvent } from '@/stores/analytics'
import { useMyMainAddress } from '@/stores/my-account'
import Image from 'next/image'
import { useState } from 'react'
import { RiPencilFill } from 'react-icons/ri'
import RemoveLinkedIdentityModal from './RemoveLinkedIdentityModal'

export default function AirdropPage() {
useTgNoScroll()

const isAdmin = useIsModerationAdmin() || true
const [isOpenRemoveAccountModal, setIsOpenRemoveAccountModal] =
useState(false)
const [openProfileModal, setOpenProfileModal] = useState(false)
const [openAddEvmModal, setOpenAddEvmModal] = useState(false)
const myAddress = useMyMainAddress()
const { evmAddress, isLoading } = useLinkedEvmAddress()
const sendEvent = useSendEvent()

return (
Expand Down Expand Up @@ -55,6 +59,17 @@ export default function AirdropPage() {
<RiPencilFill />
</Button>
</div>
{isAdmin && (
<Button
variant='redOutline'
onClick={() => {
sendEvent('remove_account_click')
setIsOpenRemoveAccountModal(true)
}}
>
Remove Account
</Button>
)}
{/* {isLoading ? (
<Skeleton className='w-12' />
) : evmAddress ? (
Expand Down Expand Up @@ -91,6 +106,10 @@ export default function AirdropPage() {
setCurrentState={() => undefined}
address={myAddress ?? ''}
/> */}
<RemoveLinkedIdentityModal
isOpen={isOpenRemoveAccountModal}
closeModal={() => setIsOpenRemoveAccountModal(false)}
/>
<SubsocialProfileModal
title='✏️ Edit Profile'
closeModal={() => setOpenProfileModal(false)}
Expand Down
59 changes: 59 additions & 0 deletions src/pages/api/datahub/remove-identity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { env } from '@/env.mjs'
import { ApiResponse, handlerWrapper } from '@/server/common'
import { getLinkedIdentity } from '@/services/datahub/identity/fetcher'
import { verifyMessage } from 'ethers'
import request, { gql } from 'graphql-request'
import { z } from 'zod'

const inputSchema = z.object({
id: z.string(),
sig: z.string(),
sessionAddress: z.string(),
})

export type ApiDatahubRemoveIdentityBody = z.infer<typeof inputSchema>
export type ApiDatahubRemoveIdentityResponse = ApiResponse
export default handlerWrapper({
inputSchema,
dataGetter: (req) => req.body,
})({
allowedMethods: ['POST'],
errorLabel: 'remove-identity',
handler: async (data, _, res) => {
const sessionAddress = verifyMessage(data.id, data.sig)
if (sessionAddress !== data.sessionAddress) {
res.status(403).json({ message: 'Unauthorized', success: false })
return
}

const linkedIdentity = await getLinkedIdentity({ sessionAddress })
if (!linkedIdentity || linkedIdentity.mainAddress !== data.id) {
res.status(403).json({ message: 'Unauthorized', success: false })
return
}

await request<
{ removedSessionsCount: number },
{ linkedIdentityId: string }
>(
env.NEXT_PUBLIC_DATAHUB_QUERY_URL,
gql`
mutation RemoveLinkedIdentity($linkedIdentityId: String!) {
linkedIdentityTerminateLinkedIdentitySession(
linkedIdentityId: $linkedIdentityId
) {
removedSessionsCount
removedExternalProvidersCount
}
}
`,
{ linkedIdentityId: data.id },
{ Authorization: `Bearer ${env.DATAHUB_QUEUE_TOKEN}` }
)

res.json({
message: 'OK',
success: true,
})
},
})
17 changes: 17 additions & 0 deletions src/services/api/mutation.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { CreateUserIdResponse } from '@/pages/api/create-user-id'
import { ApiDatahubRemoveIdentityBody } from '@/pages/api/datahub/remove-identity'
import { RevalidateChatInput } from '@/pages/api/revalidation/chat'
import { SaveFileRequest, SaveFileResponse } from '@/pages/api/save-file'
import { SaveImageResponse } from '@/pages/api/save-image'
import { useMyAccount } from '@/stores/my-account'
import mutationWrapper from '@/subsocial-query/base'
import { signMessage } from '@/utils/account'
import { apiInstance } from './utils'

export async function saveFile(content: SaveFileRequest) {
Expand Down Expand Up @@ -40,3 +43,17 @@ export function revalidateChatPage(input: RevalidateChatInput) {
return apiInstance.post('/api/revalidation/chat', input)
}
export const useRevalidateChatPage = mutationWrapper(revalidateChatPage)

async function removeMyLinkedIdentity() {
const { address, parentProxyAddress, signer } = useMyAccount.getState()
if (!address || !parentProxyAddress || !signer)
throw new Error('No address or parentProxyAddress')

const data: ApiDatahubRemoveIdentityBody = {
id: parentProxyAddress,
sessionAddress: address,
sig: await signMessage(parentProxyAddress),
}
return apiInstance.post('/api/datahub/remove-identity', data)
}
export const useRemoveMyLinkedIdentity = mutationWrapper(removeMyLinkedIdentity)

0 comments on commit d05a0a4

Please sign in to comment.