diff --git a/ui/src/gear/permissions/lib.ts b/ui/src/gear/permissions/lib.ts index 89881710..4d09dac5 100644 --- a/ui/src/gear/permissions/lib.ts +++ b/ui/src/gear/permissions/lib.ts @@ -24,11 +24,14 @@ export function denyPerms(desk: string, perms: PokePerm[]): Poke }; } -export async function sealToPassport(seal: Seal) { - return await api.thread({ +export async function sealToPassport(desk: string, seal: Seal) { + return await api.thread({ inputMark: "json", outputMark: "json", threadName: "get-passport", - body: seal + body: { + desk, + seal + } }); } diff --git a/ui/src/logic/utils.ts b/ui/src/logic/utils.ts index ca481e71..89f7a95e 100644 --- a/ui/src/logic/utils.ts +++ b/ui/src/logic/utils.ts @@ -127,3 +127,7 @@ export function randomElement(a: T[]) { export function randomIntInRange(min: number, max: number) { return Math.round(Math.random() * (max - min) + min); } + +export function capFirst(string: string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} diff --git a/ui/src/permissions/PermissionsDialog.tsx b/ui/src/permissions/PermissionsDialog.tsx index 43ade6aa..eab1dae6 100644 --- a/ui/src/permissions/PermissionsDialog.tsx +++ b/ui/src/permissions/PermissionsDialog.tsx @@ -27,6 +27,8 @@ export function PermissionsDialogInner({ const [isDropdownOpen, setIsDropdownOpen] = useState(false); const showWarning = passport.sys.length > 0; + const passportPerms = [...passport.sys, ...passport.any, ...passport.new, ...passport.rad, ...passport.app]; + return (
@@ -55,10 +57,10 @@ export function PermissionsDialogInner({ viewMode === 'Summary' ? (
{ - [...passport.sys, ...passport.any, ...passport.new, ...passport.rad].map(p => { - return p.kind.pes.map((pe, i) => { - return - }) + passportPerms.map((p, i) => { + return ( + + ) }) }
diff --git a/ui/src/permissions/SummaryRow.tsx b/ui/src/permissions/SummaryRow.tsx index f003ad8b..803bb0e7 100644 --- a/ui/src/permissions/SummaryRow.tsx +++ b/ui/src/permissions/SummaryRow.tsx @@ -1,56 +1,113 @@ +import cn from 'classnames'; import { Adjust } from '@/components/icons/Adjust'; +import BellIcon from '@/components/icons/BellIcon'; +import { ChevronDown16Icon } from '@/components/icons/ChevronDown16Icon'; import GlobeIcon from '@/components/icons/GlobeIcon'; import KeyIcon from '@/components/icons/KeyIcon'; +import SigIcon from '@/components/icons/SigIcon'; import ZapIcon from '@/components/icons/ZapIcon'; -import { PermSummary } from '@/gear'; -import React from 'react'; +import { AppPerm, PassportPerm } from '@/gear'; +import { capFirst } from '@/logic/utils'; +import React, { useCallback, useMemo, useState } from 'react'; +import exp from 'constants'; interface SummaryRowProps { /** - * A permission summary. + * A permission bucket. */ - summary: PermSummary; + perm: PassportPerm | AppPerm; } -// TODO: figured out mapping from permission to icon from Dan & Mark -const iconFromPerm = (perm: PermSummary) => { - if(perm.pers.some(p => p.vane && ['ames', 'eyre', 'gall'].includes(p.vane))) { - return ; +/** + * A row summarizing a requested permission. + * It has the description of the permission and an optional warning icon. + */ +export default function SummaryRow({ perm }: SummaryRowProps) { + const [expanded, setExpanded] = useState(false); + + // TODO: need icon identifier from perm; requested from tinnus + // for now, return random icon placeholder + const iconSeed = useMemo(() => Math.random(), []); + const iconFromPerm = (perm: PassportPerm) => { + + if (iconSeed < 0.2) { + return ; + } else if (iconSeed < 0.4) { + return ; + } else if (iconSeed < 0.6) { + return ; + } else if (iconSeed < 0.8) { + return ; + } else { + return ; + } + } + + // TODO: handle node perms + if ('node' in perm) { + return null; } - if(perm.pers.some(p => p.vane && p.vane === 'jael')) { - return ; + // TODO: handle app perms + if ('app' in perm) { + return null; } - // TODO: - // - // + const { nom, pes } = perm.kind; + const hasWarning = pes.some(pe => pe.warn !== null); + const expandable = pes.length > 0; - return ; -} - -/** - * A row summarizing a requested permission. - * It has the description of the permission and an optional warning icon. - */ -export default function SummaryRow({ summary }: SummaryRowProps) { - const { desc, warn } = summary; + const toggleExpanded = useCallback(() => { + if (!expandable) return; + setExpanded(!expanded); + }, [expanded]); return ( -
-
-
- {iconFromPerm(summary)} +
+
+
+
+ {iconFromPerm(perm)} +
+
+ {capFirst(nom)} +
-
- {desc} +
+ {hasWarning ? ( +
+ +
+ ) : null} + { + expandable ? ( +
+ +
+ ) : null + }
- {warn ? ( -
- -
- ) : null} -
+ { + expanded ? ( +
+ { + pes.map(pe => ( +
+
+ {capFirst(pe.desc)} +
+
+ )) + } +
+ ) : null + } +
) } diff --git a/ui/src/permissions/temp.ts b/ui/src/permissions/temp.ts index 25f19ec0..3a86ddca 100644 --- a/ui/src/permissions/temp.ts +++ b/ui/src/permissions/temp.ts @@ -5,65 +5,48 @@ const fakePassport: Passport = { sys: [ { kind: { - nom: 'write', + nom: 'Access your network keys', pes: [ { - desc: 'Access network keys or passwords', - have: "nil", - warn: "This app can impersonate you on the network", - pers: [ - { - name: 'write', - vane: 'jael', - tail: null, - } - ] + desc: 'Read or change your network keys', + warn: 'This permission is required for the app to work properly', + pers: [], + have: 'nil', } ] } }, + ], + any: [ { kind: { - nom: 'write', + nom: 'Send Notifications', pes: [ { - desc: 'Manage system utilities and data', + desc: 'Receive notifications via Hark', have: "nil", - warn: "This app can execute commands on your computer", - pers: [ - { - name: 'write', - vane: 'clay', - tail: null, - } - ] + warn: null, + pers: [] } ] } } ], - any: [ + new: [ { kind: { - nom: 'write', + nom: 'Manage system utilities and data', pes: [ { - desc: 'Send notifications', + desc: 'Update your Landscape and Urbit settings', have: "nil", warn: null, - pers: [ - { - name: 'write', - vane: null, - tail: null, - } - ] + pers: [] } ] } - } + }, ], - new: [], app: [], }; diff --git a/ui/src/permissions/usePassport.ts b/ui/src/permissions/usePassport.ts index c3d8c64a..e51e8c60 100644 --- a/ui/src/permissions/usePassport.ts +++ b/ui/src/permissions/usePassport.ts @@ -1,14 +1,16 @@ -import { Passport } from "@/gear"; +import { Passport, Seal, sealToPassport } from "@/gear"; import { useEffect, useState } from "react"; -import { fakePassport } from './temp'; -export default function usePassport() { +export default function usePassport({ desk, seal }: { desk: string, seal: Seal }) { const [passport, setPassport] = useState(null); + const fetchPassport = async () => { + const response = await sealToPassport(desk, seal); + setPassport(response); + }; + useEffect(() => { - setTimeout(() => { - setPassport(fakePassport); - } , 2000); + fetchPassport(); }, []); return { passport }; diff --git a/ui/src/permissions/usePermissions.ts b/ui/src/permissions/usePermissions.ts index cf35c938..2c238542 100644 --- a/ui/src/permissions/usePermissions.ts +++ b/ui/src/permissions/usePermissions.ts @@ -14,8 +14,8 @@ export default function usePermissions() { const treaty = useTreaty(host, desk); const docket = charge || treaty; const appName = getAppName(docket); - const { passport } = usePassport(); // TODO: pass in desk const [ship,] = useRemoteDesk(docket, pike, treaty?.ship); + const { passport } = usePassport({ desk, seal: treaty?.seal }); const installStatus = useInstallStatus(docket); const [presentableSeal, setPresentableSeal] = useState(null); diff --git a/ui/src/stories/SummaryRow.stories.tsx b/ui/src/stories/SummaryRow.stories.tsx index 0064649f..940ed95d 100644 --- a/ui/src/stories/SummaryRow.stories.tsx +++ b/ui/src/stories/SummaryRow.stories.tsx @@ -15,39 +15,40 @@ type Story = StoryObj; export const HasWarning: Story = { args: { - summary: { - desc: 'Access your network keys', - warn: 'This permission is required for the app to work properly', - pers: [], - have: 'nil', + perm: { + kind: { + nom: 'Access your network keys', + pes: [] + } }, }, }; export const NoWarning: Story = { args: { - summary: { - desc: 'Send notifications', - warn: null, - pers: [], - have: 'nil', + perm: { + kind: { + nom: 'Access your network keys', + pes: [] + } }, }, }; -export const Eyre: Story = { +export const Expandable: Story = { args: { - summary: { - desc: 'Communicate with ships or clearweb sites', - warn: null, - pers: [ - { - name: 'write', - vane: 'eyre', - tail: null, - } - ], - have: 'nil', + perm: { + kind: { + nom: 'Access your network keys', + pes: [ + { + desc: 'Read or change your network keys', + warn: 'This permission is required for the app to work properly', + pers: [], + have: 'nil', + } + ] + } }, }, };