Skip to content

Commit

Permalink
chore(profile): redirect from /a/ to /p/ (#1796)
Browse files Browse the repository at this point in the history
* chore(profile): profile from account

* wip

* fix(profile): connected addresses

* chore(profile): default /p/ route

* wip:comment

* wip

* fix(profile): getAccountFromAddress

* feat(account): check accountURNs match

* chore(account): accountURN validation in account trpc

* fix(profile): veiw others profile when not logged-in
  • Loading branch information
pillowboy authored Feb 28, 2023
1 parent 331623d commit 576c23f
Show file tree
Hide file tree
Showing 26 changed files with 1,088 additions and 2,172 deletions.
45 changes: 18 additions & 27 deletions apps/profile/app/components/profile/links/links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,26 @@ export const Links = ({ links, isOwner = false, displayName }: LinksProps) => {
providerIcon: imageFromAddressType(link.provider),
}))
.map((link, i: number) => (
<button
<a
key={`${link.name}-${link.url}-${i}`}
className="
bg-gray-100 hover:bg-gray-200
transition-colors
rounded-full
justify-center
items-center
w-full
py-5"
href={link.url}
className="flex flex-row justify-center items-center space-x-2.5
bg-gray-100 hover:bg-gray-200 transition-colors
rounded-full justify-center items-center w-full py-5"
rel="noreferrer"
target="_blank"
>
<a
href={link.url}
className="flex flex-row justify-center items-center space-x-2.5"
rel="noreferrer"
target="_blank"
>
{link.providerIcon && (
<img
src={link.providerIcon}
alt="Something went wrong..."
className="w-5 h-5"
/>
)}
<Text weight="medium" className="text-gray-600">
{link.name}
</Text>
</a>
</button>
{link.providerIcon && (
<img
src={link.providerIcon}
alt="Something went wrong..."
className="w-5 h-5"
/>
)}
<Text weight="medium" className="text-gray-600">
{link.name}
</Text>
</a>
))}
</div>
)
Expand Down
46 changes: 21 additions & 25 deletions apps/profile/app/helpers/nfts.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import {
gatewayFromIpfs,
getAuthzHeaderConditionallyFromToken,
} from '@kubelt/utils'
import { gatewayFromIpfs } from '@kubelt/utils'
import { getGalaxyClient } from './clients'
import { getAccountProfile, getAddressProfile } from './profile'
import { getAccountProfile } from './profile'

import type { AddressURN } from '@kubelt/urns/address'
import type { Nft } from '@kubelt/galaxy-client'
import type { AccountURN } from '@kubelt/urns/account'
import { AccountURNSpace } from '@kubelt/urns/account'
import type { Gallery, Nft } from '@kubelt/galaxy-client'
/**
* Nfts are being sorted server-side
* this function then allows to merge client Nfts with newly-fetched Nfts
Expand Down Expand Up @@ -131,19 +129,13 @@ export const decorateNfts = (ownedNfts: any) => {
}

/**
* Returns own gallery if JWT is provided or
* target address gallery for which only
* Returns target address gallery for which only
* owner property is required.
* @param owner AddressURN of target profile. Can be undefined if JWT is provided.
* @param jwt JWT of requester
* @param owner AccountURN of target profile. Can be undefined if JWT is provided.
* @returns Gallery or empty array
*/
export const getGallery = async (owner: string, jwt?: string) => {
// TODO: get from account
const profile = jwt
? await getAccountProfile(jwt)
: await getAddressProfile(owner as AddressURN)

export const getGallery = async (accountURN: AccountURN) => {
const profile = await getAccountProfile({ accountURN })
const { gallery } = profile

return gallery || []
Expand All @@ -166,7 +158,7 @@ const getMoreNfts = (fetcher: any, request: string) => {
}

export const getMoreNftsGallery = (fetcher: any, accountURN: string) => {
const query = generateQuery([{ name: 'owner', value: accountURN }])
const query = generateQuery([{ name: 'accountURN', value: accountURN }])
const request = `/nfts/gallery?${query}`
getMoreNfts(fetcher, request)
}
Expand Down Expand Up @@ -219,13 +211,17 @@ export const getMoreNftsAllCollections = (

// ------ end of the VERY HIGHLY IMPURE FUNCTIONS TO FETCH NFTS

export const getGalleryWithMetadata = async (owner: string, jwt?: string) => {
const gallery = await getGallery(owner, jwt)
export const getGalleryWithMetadata = async (accountURN: AccountURN) => {
const gallery = await getGallery(accountURN)

if (!gallery || !gallery.length) {
return { gallery: [] }
}

return await getGalleryMetadata(gallery)
}

export const getGalleryMetadata = async (gallery: Gallery[]) => {
const galaxyClient = await getGalaxyClient()

const { getNFTMetadataBatch: metadata } = await galaxyClient.getNFTMetadata(
Expand All @@ -238,18 +234,18 @@ export const getGalleryWithMetadata = async (owner: string, jwt?: string) => {
})
),
},
// Optional for when called by
// a non authenticated visitor
// of a public profile
getAuthzHeaderConditionallyFromToken(jwt)
/**
* Since gallery exists in public-only mode
* we do not need to specify JWT here
*/
{}
)

const ownedNfts: decoratedNft[] | undefined = metadata?.ownedNfts.map(
(nft) => {
return decorateNft(nft as Nft)
}
)

// Setup og tag data
// check generate and return og image

Expand Down
45 changes: 18 additions & 27 deletions apps/profile/app/helpers/profile.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import type { Profile, Link, Gallery, Node } from '@kubelt/galaxy-client'
import { CryptoAddressType, OAuthAddressType } from '@kubelt/types/address'
import type { AddressURN } from '@kubelt/urns/address'
import { getAuthzHeaderConditionallyFromToken } from '@kubelt/utils'
import { getGalaxyClient } from '~/helpers/clients'
import { imageFromAddressType } from './icons'

export const getAccountProfile = async (jwt: string) => {
import type { FullProfile } from '~/types'
import type { AccountURN } from '@kubelt/urns/account'

export const getAccountProfile = async ({
jwt,
accountURN,
}: {
jwt?: string
accountURN?: AccountURN
}) => {
const galaxyClient = await getGalaxyClient()

const profileRes = await galaxyClient.getProfile(
undefined,
accountURN ? { targetAccountURN: accountURN } : undefined,
getAuthzHeaderConditionallyFromToken(jwt)
)

const { profile, links, gallery, connectedAddresses } = profileRes
return { profile, links, gallery, connectedAddresses } as {
profile: Profile
links: Link[]
gallery: Gallery[]
connectedAddresses: Node[]
}
return {
...profile,
links,
gallery,
addresses: connectedAddresses,
} as FullProfile
}

export const getAuthorizedApps = async (jwt: string) => {
Expand All @@ -40,26 +47,10 @@ export const getAccountAddresses = async (jwt: string) => {
getAuthzHeaderConditionallyFromToken(jwt)
)

const addresses = addressesRes.connectedAddresses
const addresses = addressesRes.addresses
return addresses
}

export const getAddressProfile = async (addressURN: AddressURN) => {
const galaxyClient = await getGalaxyClient()
const addressProfile = await galaxyClient.getProfileFromAddress({
addressURN,
})

const profile = addressProfile

return {
...profile.profile,
links: profile.links,
gallery: profile.gallery,
connectedAccounts: profile.connectedAddresses,
}
}

export const getAddressProfiles = async (
jwt: string,
addressURNList: AddressURN[]
Expand Down
13 changes: 4 additions & 9 deletions apps/profile/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import HeadNav, { links as headNavLink } from '~/components/head-nav'

import * as gtag from '~/utils/gtags.client'
import { getProfileSession } from './utils/session.server'
import { getRedirectUrlForProfile } from './utils/redirects.server'
import { AccountURNSpace } from '@kubelt/urns/account'
import { parseJwt } from './utils/session.server'
import { getAccountProfile } from './helpers/profile'
import type { AccountURN } from '@kubelt/urns/account'
Expand Down Expand Up @@ -91,19 +91,14 @@ export const loader: LoaderFunction = async ({ request }) => {

accountURN = parseJwt(jwt).sub as AccountURN

const fetchedLoggedInProfile = await getAccountProfile(jwt)
const fetchedLoggedInProfile = await getAccountProfile({ jwt })

if (!fetchedLoggedInProfile)
throw new Error('Could not retrieve logged in use profile.')

loggedInUserProfile = {
...fetchedLoggedInProfile.profile,
links: fetchedLoggedInProfile.links,
gallery: fetchedLoggedInProfile.gallery,
addresses: fetchedLoggedInProfile.connectedAddresses,
}
loggedInUserProfile = fetchedLoggedInProfile

basePath = getRedirectUrlForProfile(loggedInUserProfile)
basePath = `/p/${AccountURNSpace.decode(accountURN)}`
}

return json({
Expand Down
51 changes: 20 additions & 31 deletions apps/profile/app/routes/$type.$address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
HiOutlineQuestionMarkCircle,
} from 'react-icons/hi'

import { getProfileSession } from '~/utils/session.server'
import { getProfileSession, parseJwt } from '~/utils/session.server'
import { getGalaxyClient } from '~/helpers/clients'
import { ogImageFromProfile } from '~/helpers/ogImage'

Expand All @@ -29,15 +29,13 @@ import {
gatewayFromIpfs,
getAuthzHeaderConditionallyFromToken,
} from '@kubelt/utils'
import type { AddressURN } from '@kubelt/urns/address'
import { AddressURNSpace } from '@kubelt/urns/address'

import { Cover } from '~/components/profile/cover/Cover'
import ProfileTabs from '~/components/profile/tabs/tabs'
import ProfileLayout from '~/components/profile/layout'

import defaultOG from '~/assets/Rollup_profiles_OG.png'
import { getRedirectUrlForProfile } from '~/utils/redirects.server'
import {
CryptoAddressType,
NodeType,
Expand All @@ -57,27 +55,26 @@ export const loader: LoaderFunction = async ({ request, params }) => {
const session = await getProfileSession(request)
if (!address) throw new Error('No address provided in URL')

// redirect from accountURN to first addressURNs
if (type === 'p') {
const { addresses } = await galaxyClient.getConnectedAddressesFromAccount({
accountURN: AccountURNSpace.urn(address),
})
// redirect from any addressURN to its addressURNs
if (type === 'a') {
const { account }: { account: AccountURN } =
await galaxyClient.getAccountUrnFromAddress({
addressURN: AddressURNSpace.urn(address),
})

return redirect(
`/a/${AddressURNSpace.decode(addresses?.[0].baseUrn as AddressURN)}`
)
return redirect(`/p/${AccountURNSpace.decode(account)}`)
}

const urn = AddressURNSpace.urn(address)
const accountURN = AccountURNSpace.urn(address) as AccountURN

// if not handle is this let's assume this is an idref
let profile, jwt
try {
const user = session.get('user')
jwt = user?.accessToken
profile = await galaxyClient.getProfileFromAddress(
profile = await galaxyClient.getProfile(
{
addressURN: urn,
targetAccountURN: accountURN,
},
getAuthzHeaderConditionallyFromToken(jwt)
)
Expand All @@ -93,14 +90,7 @@ export const loader: LoaderFunction = async ({ request, params }) => {
addresses: profile.connectedAddresses || [],
}

if (type === 'a') {
const redirectUrl = getRedirectUrlForProfile(profile)
const originalRoute = `/${type}/${address}`
//Redirect if we've found a better route
if (redirectUrl && originalRoute !== redirectUrl)
return redirect(redirectUrl)
//otherwise stay on current route
} else if (type === 'u') {
if (type === 'u') {
//TODO: galaxy search by handle
console.error('Not implemented')
} else {
Expand All @@ -115,7 +105,8 @@ export const loader: LoaderFunction = async ({ request, params }) => {
const splittedUrl = request.url.split('/')
const path = splittedUrl[splittedUrl.length - 1]

const matches = profile.addresses?.filter((addr) => urn === addr.baseUrn)
// Check if the accountURN in jwt matches with accountURN in URL
const isOwner = jwt ? parseJwt(jwt).sub === accountURN : false

const cryptoAddresses = profile.addresses?.filter(
(addr) => addr.rc.node_type === NodeType.Crypto
Expand All @@ -125,14 +116,14 @@ export const loader: LoaderFunction = async ({ request, params }) => {
uname: profile.handle || address,
ogImage: ogImage || defaultOG,
profile,
addressURN: urn,
accountURN,
cryptoAddresses,
path,
isOwner: jwt && matches && matches.length > 0 ? true : false,
isOwner,
})
} catch (e) {
console.log(
`Galaxy did not return a profile for address ${urn}. Moving on.`
`Galaxy did not return a profile for address ${accountURN}. Moving on.`
)
throw new Response('No address found', { status: 404 })
}
Expand Down Expand Up @@ -173,13 +164,13 @@ export const meta: MetaFunction = ({
const UserAddressLayout = () => {
//TODO: this needs to be optimized so profile isn't fetched from the loader
//but used from context alone.
const { profile, cryptoAddresses, path, isOwner, addressURN } =
const { profile, cryptoAddresses, path, isOwner, accountURN } =
useLoaderData<{
profile: FullProfile
cryptoAddresses: Node[]
path: string
isOwner: boolean
addressURN: string
accountURN: string
}>()

const ctx = useOutletContext<{
Expand All @@ -188,7 +179,6 @@ const UserAddressLayout = () => {
// from root.tsx
// but if not logged in
// is null...
accountURN: AccountURN
}>()

const finalProfile = profile ?? ctx.profile
Expand Down Expand Up @@ -305,10 +295,9 @@ const UserAddressLayout = () => {
>
<Outlet
context={{
addressURN: addressURN,
accountURN,
profile: finalProfile,
cryptoAddresses,
path,
isOwner,
}}
/>
Expand Down
Loading

0 comments on commit 576c23f

Please sign in to comment.