-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #199 from OpenWebhook/display-store-config
Display store config
- Loading branch information
Showing
16 changed files
with
305 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
diff --git a/node_modules/use-http/dist/cjs/types.d.ts b/node_modules/use-http/dist/cjs/types.d.ts | ||
index e33cb72..37a643e 100644 | ||
--- a/node_modules/use-http/dist/cjs/types.d.ts | ||
+++ b/node_modules/use-http/dist/cjs/types.d.ts | ||
@@ -215,4 +215,5 @@ export declare type NonObjectKeysOf<T> = { | ||
}[keyof T]; | ||
export declare type ObjectValuesOf<T extends Record<string, any>> = Exclude<Exclude<Extract<ValueOf<T>, object>, never>, Array<any>>; | ||
export declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; | ||
+//@ts-ignore | ||
export declare type Flatten<T> = Pick<T, NonObjectKeysOf<T>> & UnionToIntersection<ObjectValuesOf<T>>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
src/ProxyStatus/HelpButton.component.tsx → ...vBar/ProxyStatus/HelpButton.component.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import DataWell from "@pluralsight/ps-design-system-datawell"; | ||
import Link from "@pluralsight/ps-design-system-link/dist/esm/react"; | ||
import { Heading, List, P } from "@pluralsight/ps-design-system-text"; | ||
import React from "react"; | ||
|
||
export const StoreConfigInnerDialog = ({ | ||
availableStores, | ||
storageLimit, | ||
defaultTargets, | ||
accessConfig, | ||
userHasAccessToStore, | ||
}: { | ||
availableStores: { url: string; display: string }[]; | ||
accessConfig: { type: "public" | "private"; sublabel: string }; | ||
storageLimit?: number; | ||
defaultTargets?: string[]; | ||
userHasAccessToStore: boolean; | ||
}) => { | ||
return ( | ||
<> | ||
<Heading> | ||
<h1>Store Config</h1> | ||
</Heading> | ||
<div style={{ display: "flex" }}> | ||
<DataWell label="Access" subLabel={accessConfig.sublabel}> | ||
{accessConfig.type} {accessConfig.type === "public" ? "⚠️" : null} | ||
</DataWell> | ||
{storageLimit && ( | ||
<DataWell label="Storage Limit">{storageLimit}</DataWell> | ||
)} | ||
{defaultTargets && ( | ||
<DataWell label="Default Target"> | ||
<List> | ||
{defaultTargets.map((target) => ( | ||
<List.Item>{target}</List.Item> | ||
))} | ||
</List> | ||
</DataWell> | ||
)} | ||
</div> | ||
|
||
{userHasAccessToStore | ||
? "You have access to this store" | ||
: "You don't have access to this store"} | ||
|
||
<Heading> | ||
<h1>Your private webhooks stores</h1> | ||
</Heading> | ||
|
||
<List> | ||
{availableStores.length > 0 | ||
? availableStores.map((store) => ( | ||
<List.Item> | ||
<Link> | ||
<a href={store.url}>{store.display}</a> | ||
</Link> | ||
</List.Item> | ||
)) | ||
: null} | ||
</List> | ||
|
||
<P> | ||
<Link> | ||
<a href="https://www.openwebhook.io/docs/intro/#authentication"> | ||
WebhookStore access documentation | ||
</a> | ||
</Link> | ||
</P> | ||
|
||
<P> | ||
<Link> | ||
<a href="https://www.openwebhook.io/docs/intro/#%EF%B8%8F-public-organisation-membership"> | ||
You don't see your organisation here? | ||
</a> | ||
</Link> | ||
</P> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import { Label } from "@pluralsight/ps-design-system-text"; | ||
import { Below } from "@pluralsight/ps-design-system-position"; | ||
|
||
import React, { useContext, useEffect, useState } from "react"; | ||
import Button from "@pluralsight/ps-design-system-button"; | ||
import { StoreConfigInnerDialog } from "./StoreConfigDialog"; | ||
import Dialog from "@pluralsight/ps-design-system-dialog"; | ||
import useFetch from "use-http"; | ||
import { WebhookStoreUrlContext } from "../WebhookStoreUrl/WebhookStoreUrl.context"; | ||
import { ACCESS_TOKEN_KEY, IDENTITY_TOKEN_KEY } from "../../local-storage"; | ||
import { decodeJWT } from "../../utils/decode-jwt"; | ||
|
||
export type AuthMetadata = | ||
| { protected: true; protectionRule: "hostname webhook.store" } | ||
| { protected: true; protectionRule: "github-org"; ghOrg: string } | ||
| { protected: false }; | ||
|
||
export const StoreConfigNavItem = () => { | ||
const [isClicked, setClicked] = useState<boolean>(false); | ||
|
||
const [authConfig, setAuthConfig] = useState<AuthMetadata>({ | ||
protected: false, | ||
}); | ||
const [storeConfig, setStoreConfig] = useState<{ | ||
maxNumberOfWebhookPerHost?: number; | ||
defaultTarget?: string[]; | ||
userHasAccessToStore: boolean; | ||
}>({ userHasAccessToStore: false }); | ||
|
||
const { value: webhookStoreUrl } = useContext(WebhookStoreUrlContext); | ||
const accessToken = localStorage.getItem(ACCESS_TOKEN_KEY); | ||
const { get, response } = useFetch(webhookStoreUrl, { | ||
headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : {}, | ||
}); | ||
const idToken = localStorage.getItem(IDENTITY_TOKEN_KEY); | ||
const identityToken = | ||
idToken && | ||
decodeJWT<{ name: string; ghOrganisations: string[] }, any>(idToken); | ||
|
||
useEffect(() => { | ||
getConfigs(); | ||
}, []); | ||
|
||
async function getConfigs() { | ||
const initialiseAuthConfig = await get("auth-metadata"); | ||
if (response.ok) setAuthConfig(initialiseAuthConfig); | ||
const initialiseStoreConfig = await get("store-metadata"); | ||
if (response.ok) | ||
setStoreConfig({ ...initialiseStoreConfig, userHasAccessToStore: true }); | ||
} | ||
|
||
const accessConfig = describeAccessFromAuthConfig( | ||
authConfig, | ||
webhookStoreUrl | ||
); | ||
const availableStores = identityToken | ||
? [ | ||
{ | ||
url: `https://${identityToken.payload.name}.github-org.webhook.store/?access_token=${idToken}`, | ||
display: `${identityToken.payload.name}.github-org.webhook.store`, | ||
}, | ||
...identityToken.payload.ghOrganisations.map((orgName) => ({ | ||
url: `https://${orgName}.github.webhook.store/?access_token=${idToken}`, | ||
display: `${orgName}.github-org.webhook.store`, | ||
})), | ||
] | ||
: [ | ||
{ | ||
url: "https://github.webhook.store", | ||
display: "github.webhook.store", | ||
}, | ||
]; | ||
const defaultTargets = storeConfig.defaultTarget; | ||
const storageLimit = storeConfig.maxNumberOfWebhookPerHost; | ||
|
||
return ( | ||
<Below | ||
show={ | ||
<Dialog> | ||
<StoreConfigInnerDialog | ||
accessConfig={accessConfig} | ||
availableStores={availableStores} | ||
defaultTargets={defaultTargets} | ||
storageLimit={storageLimit} | ||
userHasAccessToStore={storeConfig.userHasAccessToStore} | ||
/> | ||
</Dialog> | ||
} | ||
when={isClicked} | ||
> | ||
<Button | ||
appearance={Button.appearances.flat} | ||
onClick={(_) => setClicked(!isClicked)} | ||
> | ||
<Label size={Label.sizes.xSmall}> | ||
Store Config {authConfig.protected ? null : "⚠️"} | ||
</Label> | ||
</Button> | ||
</Below> | ||
); | ||
}; | ||
|
||
const describeAccessFromAuthConfig = ( | ||
authConfig: AuthMetadata, | ||
webhookStoreUrl: string | ||
): { type: "public" | "private"; sublabel: string } => { | ||
if (!authConfig.protected) { | ||
return { type: "public", sublabel: "Anyone with the link" }; | ||
} | ||
|
||
if (authConfig.protectionRule === "github-org") { | ||
return { | ||
type: "private", | ||
sublabel: `Only members of ${authConfig.ghOrg} on GitHub`, | ||
}; | ||
} | ||
|
||
if (authConfig.protectionRule === "hostname webhook.store") { | ||
const webhookStoreDomain = new URL(webhookStoreUrl).hostname; | ||
if (webhookStoreDomain.endsWith(".github.webhook.store")) { | ||
const githubUserName = | ||
webhookStoreDomain.split(".")[webhookStoreDomain.split(".").length - 4]; | ||
return { | ||
type: "private", | ||
sublabel: `Only Github user ${githubUserName}`, | ||
}; | ||
} | ||
if (webhookStoreDomain.endsWith(".github-org.webhook.store")) { | ||
const githubOrgaName = | ||
webhookStoreDomain.split(".")[webhookStoreDomain.split(".").length - 4]; | ||
return { | ||
type: "private", | ||
sublabel: `Only members of ${githubOrgaName} on GitHub`, | ||
}; | ||
} | ||
return { type: "public", sublabel: "Anyone with the link" }; | ||
} | ||
|
||
return { type: "public", sublabel: "Anyone with the link" }; | ||
}; |
4 changes: 2 additions & 2 deletions
4
src/User/LoginOrDisplayUser.tsx → src/NavBar/User/LoginOrDisplayUser.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.