forked from coracle/caravel
Add identity endpoint
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { A, useLocation } from "@solidjs/router"
|
||||
import { A, useLocation, useNavigate } from "@solidjs/router"
|
||||
import { createEffect, createMemo, createSignal, For, onCleanup, Show } from "solid-js"
|
||||
import Fuse from "fuse.js"
|
||||
import { eventStore, primeProfiles, useActiveAccount, useProfilePicture } from "../lib/nostr"
|
||||
import { useAdminCheck, useTenantRelays, type Relay } from "../lib/hooks"
|
||||
import { useIdentity, useTenantRelays, type Relay } from "../lib/hooks"
|
||||
import serverIcon from "../assets/server.svg"
|
||||
import Modal from "./Modal"
|
||||
|
||||
@@ -32,15 +32,16 @@ function RelayIcon() {
|
||||
|
||||
export default function AppShell(props: { children?: any }) {
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
const account = useActiveAccount()
|
||||
const picture = useProfilePicture(() => account()?.pubkey)
|
||||
const [adminCheck] = useAdminCheck(() => account()?.id)
|
||||
const [identity] = useIdentity(() => account()?.pubkey)
|
||||
const [tenantRelays] = useTenantRelays()
|
||||
const [profile, setProfile] = createSignal<Profile>({})
|
||||
const [searchOpen, setSearchOpen] = createSignal(false)
|
||||
const [searchQuery, setSearchQuery] = createSignal("")
|
||||
|
||||
const isAdmin = createMemo(() => !!adminCheck()?.is_admin)
|
||||
const isAdmin = createMemo(() => !!identity()?.is_admin)
|
||||
const username = createMemo(() => profile().name || profile().display_name || shortenPubkey(account()?.pubkey))
|
||||
const nip05 = createMemo(() => profile().nip05 || "No NIP-05")
|
||||
const searchedRelays = createMemo<Relay[]>(() => {
|
||||
@@ -82,6 +83,12 @@ export default function AppShell(props: { children?: any }) {
|
||||
})
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
const currentIdentity = identity()
|
||||
if (!currentIdentity || currentIdentity.is_admin || currentIdentity.is_tenant || location.pathname === "/") return
|
||||
navigate("/", { replace: true })
|
||||
})
|
||||
|
||||
const myResources = [{ href: "/relays", label: "My Relays" }]
|
||||
const adminResources = [
|
||||
{ href: "/admin/tenants", label: "Tenants" },
|
||||
|
||||
@@ -71,6 +71,12 @@ export type Invoice = {
|
||||
period_end: number
|
||||
}
|
||||
|
||||
export type Identity = {
|
||||
pubkey: string
|
||||
is_admin: boolean
|
||||
is_tenant: boolean
|
||||
}
|
||||
|
||||
export type CreateRelayInput = {
|
||||
tenant?: string
|
||||
subdomain: string
|
||||
@@ -168,6 +174,10 @@ export function listPlans() {
|
||||
return callApi<undefined, Plan[]>("GET", "/plans")
|
||||
}
|
||||
|
||||
export function getIdentity() {
|
||||
return callApi<undefined, Identity>("GET", "/identity")
|
||||
}
|
||||
|
||||
export function getPlan(id: string) {
|
||||
return callApi<undefined, Plan>("GET", `/plans/${id}`)
|
||||
}
|
||||
|
||||
+38
-24
@@ -1,10 +1,9 @@
|
||||
import { createResource } from "solid-js"
|
||||
import { Relay as NostrRelay, RelayManagement } from "applesauce-relay"
|
||||
import {
|
||||
ApiError,
|
||||
createRelay,
|
||||
createTenant,
|
||||
deactivateRelay,
|
||||
getIdentity,
|
||||
getRelay,
|
||||
getTenant,
|
||||
listRelays,
|
||||
@@ -14,31 +13,61 @@ import {
|
||||
updateRelay,
|
||||
updateTenantBilling,
|
||||
type CreateRelayInput,
|
||||
type Identity,
|
||||
type Relay,
|
||||
type Tenant,
|
||||
type UpdateRelayInput,
|
||||
} from "./api"
|
||||
import { getActivePubkey, getActiveSigner } from "./nostr"
|
||||
|
||||
type IdentityCache = {
|
||||
pubkey: string
|
||||
value: Identity
|
||||
}
|
||||
|
||||
let identityCache: IdentityCache | undefined
|
||||
let identityInflight: Promise<Identity> | undefined
|
||||
let identityInflightPubkey: string | undefined
|
||||
|
||||
function requireActivePubkey() {
|
||||
const pubkey = getActivePubkey()
|
||||
if (!pubkey) throw new Error("Not logged in")
|
||||
return pubkey
|
||||
}
|
||||
|
||||
async function ensureActiveTenant() {
|
||||
try {
|
||||
await createTenant()
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError && e.status === 422) return
|
||||
throw e
|
||||
async function loadIdentity(pubkey?: string) {
|
||||
if (!pubkey) throw new Error("Not logged in")
|
||||
|
||||
if (identityCache?.pubkey === pubkey) {
|
||||
return identityCache.value
|
||||
}
|
||||
|
||||
if (identityInflight && identityInflightPubkey === pubkey) {
|
||||
return identityInflight
|
||||
}
|
||||
|
||||
const request = getIdentity().then((identity) => {
|
||||
identityCache = { pubkey, value: identity }
|
||||
return identity
|
||||
}).finally(() => {
|
||||
if (identityInflightPubkey === pubkey) {
|
||||
identityInflight = undefined
|
||||
identityInflightPubkey = undefined
|
||||
}
|
||||
})
|
||||
|
||||
identityInflight = request
|
||||
identityInflightPubkey = pubkey
|
||||
return request
|
||||
}
|
||||
|
||||
export function useIdentity(source: () => string | undefined) {
|
||||
return createResource(source, loadIdentity)
|
||||
}
|
||||
|
||||
export function useTenant() {
|
||||
return createResource(async () => {
|
||||
const pubkey = requireActivePubkey()
|
||||
await ensureActiveTenant()
|
||||
return getTenant(pubkey)
|
||||
})
|
||||
}
|
||||
@@ -46,7 +75,6 @@ export function useTenant() {
|
||||
export function useTenantRelays() {
|
||||
return createResource(async () => {
|
||||
const pubkey = requireActivePubkey()
|
||||
await ensureActiveTenant()
|
||||
return listTenantRelays(pubkey)
|
||||
})
|
||||
}
|
||||
@@ -54,7 +82,6 @@ export function useTenantRelays() {
|
||||
export function useTenantInvoices() {
|
||||
return createResource(async () => {
|
||||
const pubkey = requireActivePubkey()
|
||||
await ensureActiveTenant()
|
||||
return listTenantInvoices(pubkey)
|
||||
})
|
||||
}
|
||||
@@ -78,21 +105,8 @@ export function useAdminTenantDetail(pubkey: () => string) {
|
||||
})
|
||||
}
|
||||
|
||||
export function useAdminCheck(source: () => string | undefined) {
|
||||
return createResource(source, async () => {
|
||||
try {
|
||||
await listTenants()
|
||||
return { is_admin: true }
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError && e.status === 403) return { is_admin: false }
|
||||
throw e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function createRelayForActiveTenant(input: CreateRelayInput) {
|
||||
const pubkey = requireActivePubkey()
|
||||
await ensureActiveTenant()
|
||||
return createRelay({ ...input, tenant: pubkey })
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user