Skip to content

Commit a73448a

Browse files
authored
Merge pull request #376 from oasisprotocol/lw/view-granted-logs
Show "View logs" button in explore page if someone grants you permission
2 parents 2d74902 + cb3ab50 commit a73448a

4 files changed

Lines changed: 65 additions & 3 deletions

File tree

.changelog/376.feature.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Show "View logs" button in explore page if someone grants you permission
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { type FC } from 'react'
2+
import { Link } from 'react-router-dom'
3+
import { useGetRuntimeRoflmarketInstances, type RoflApp } from '../../nexus/api'
4+
import { Button } from '@oasisprotocol/ui-library/src/components/ui/button'
5+
import { useAccount } from 'wagmi'
6+
import { hasViewLogsPermission } from '../../utils/hasViewLogsPermission'
7+
import { isMachineRemoved } from '../MachineStatusIcon/isMachineRemoved'
8+
9+
type ViewWithOnlyLogsPermissionProps = {
10+
app: RoflApp
11+
network: 'mainnet' | 'testnet'
12+
}
13+
14+
export const ViewWithOnlyLogsPermission: FC<ViewWithOnlyLogsPermissionProps> = ({ app, network }) => {
15+
const { address } = useAccount()
16+
const machinesQuery = useGetRuntimeRoflmarketInstances(network, 'sapphire', {
17+
limit: 100,
18+
offset: 0,
19+
deployed_app_id: app.id,
20+
})
21+
const machinesWithOnlyLogsPermission =
22+
address && machinesQuery.data?.data.instances
23+
? machinesQuery.data.data.instances
24+
.filter(machine => !isMachineRemoved(machine))
25+
.filter(machine => hasViewLogsPermission(machine, address))
26+
: []
27+
28+
if (machinesWithOnlyLogsPermission.length <= 0) return
29+
return (
30+
<div className="flex flex-col gap-2">
31+
{machinesWithOnlyLogsPermission.map(machine => (
32+
<Button key={machine.id} variant="default" asChild>
33+
{/* TODO: Link to logs subpage. But shadcn does not support routed tabs nicely. */}
34+
<Link to={`/dashboard/machines/${machine.provider}/instances/${machine.id}`}>View logs</Link>
35+
</Button>
36+
))}
37+
</div>
38+
)
39+
}

src/components/AppCard/index.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ import { AppStatusIcon } from '../AppStatusIcon'
99
import { cn } from '@oasisprotocol/ui-library/src/lib/utils'
1010
import { trimLongString } from '../../utils/trimLongString'
1111
import { formatDistanceToNow, parseISO } from 'date-fns'
12+
import { useAccount } from 'wagmi'
13+
import { ViewWithOnlyLogsPermission } from './ViewWithOnlyLogsPermission'
1214

1315
type AppCardProps = {
1416
app: RoflApp
15-
network: string
17+
network: 'mainnet' | 'testnet'
1618
type?: 'explore' | 'dashboard'
1719
}
1820

1921
export const AppCard: FC<AppCardProps> = ({ app, network, type }) => {
22+
const { address } = useAccount()
23+
2024
return (
2125
<Card className="rounded-md">
2226
<CardHeader className="">
@@ -61,14 +65,16 @@ export const AppCard: FC<AppCardProps> = ({ app, network, type }) => {
6165
</div>
6266
)}
6367
</CardContent>
64-
<CardFooter className="flex justify-between">
68+
<CardFooter className="flex justify-between only:*:grow">
6569
{type === 'dashboard' && (
6670
<Button variant="secondary" asChild>
6771
<Link to={`/dashboard/apps/${app.id}`}>View details</Link>
6872
</Button>
6973
)}
7074

71-
<Button variant="secondary" asChild className={cn('bg-background', type === 'explore' && 'w-full')}>
75+
{type === 'explore' && address && <ViewWithOnlyLogsPermission app={app} network={network} />}
76+
77+
<Button variant="secondary" asChild className="bg-background">
7278
<a
7379
href={`https://explorer.oasis.io/${network}/sapphire/rofl/app/${app.id}`}
7480
target="_blank"

src/utils/hasViewLogsPermission.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { RoflMarketInstance } from '../nexus/api'
2+
import * as oasis from '@oasisprotocol/client'
3+
import { getEvmBech32Address } from './helpers'
4+
5+
export function hasViewLogsPermission(machine: RoflMarketInstance, account: `0x${string}`) {
6+
const metadata = machine.deployment?.metadata as undefined | { 'net.oasis.scheduler.permissions'?: string }
7+
if (!metadata?.['net.oasis.scheduler.permissions']) return false
8+
9+
const oasisAddress = getEvmBech32Address(account)
10+
// Parse oWhsb2cudmlld4FVABUafBL3j0oDGd4HRygbj5UK92DG to { log.view: [oasis1qq235lqj77855qcemcr5w2qm372s4amqcc4v3ztc] }
11+
const permissions = oasis.misc.fromCBOR(
12+
oasis.misc.fromBase64(metadata['net.oasis.scheduler.permissions']),
13+
) as { 'log.view'?: Uint8Array[] }
14+
15+
return permissions['log.view']?.find(a => oasis.staking.addressToBech32(a) === oasisAddress)
16+
}

0 commit comments

Comments
 (0)