Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: add credential based signin for dialog and webapp #46

Merged
merged 5 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 23 additions & 27 deletions example-web/my-app/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import "./App.css";

function App() {
const [password, setPassword] = useState("");
const handleAuth = () => {
window.postMessage({ type: "initAuth" }, "*");

const handleRequestIdentifier = () => {
window.postMessage({ type: "init-req-identifier" }, "*");
};

const handleRequestCredential = () => {
window.postMessage({ type: "init-req-credential" }, "*");
};

const handleLogout = () => {
Expand All @@ -23,32 +28,23 @@ function App() {
<div className="App">
<header className="App-header">
<img src={logo} alt="logo" />
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 32 32"
id="loading"
className="animate-spin h-3 w-3"
>
<g data-name="Loader">
<path
fill="currentColor"
d="M29.89 15.81a2.51 2.51 0 1 0-5 .45 9.65 9.65 0 0 1-1.68 6.34 10.24 10.24 0 0 1-5.74 4 10.71 10.71 0 0 1-7.38-.7 11.44 11.44 0 0 1-5.48-5.62A12.07 12.07 0 0 0 9.46 27 12.58 12.58 0 0 0 17.9 29a13.31 13.31 0 0 0 8.18-4 14 14 0 0 0 3.81-8.75v-.08A2.29 2.29 0 0 0 29.89 15.81zM7.11 15.74A9.65 9.65 0 0 1 8.79 9.4a10.24 10.24 0 0 1 5.74-4 10.71 10.71 0 0 1 7.38.7 11.44 11.44 0 0 1 5.48 5.62A12.07 12.07 0 0 0 22.54 5 12.58 12.58 0 0 0 14.1 3 13.31 13.31 0 0 0 5.92 7a14 14 0 0 0-3.81 8.75v.08a2.29 2.29 0 0 0 0 .37 2.51 2.51 0 1 0 5-.45z"
></path>
</g>
</svg>
<input
id="aid-input"
type="password"
style={{ visibility: "hidden" }}
onChange={(e) => {
console.log(e);
setPassword(e.target.value);
}}
/>
<div className="flex flex-row gap-x-2 mt-2">
<Button variant="contained" onClick={handleRequestIdentifier}>
Authenticate with AID
</Button>
{/* <Button variant="contained" onClick={handleRequestCredential}>
Authenticate with Credential
</Button> */}
</div>
<p>
{storageToken ? (
<Button variant="contained" onClick={handleLogout}>
Logout
</Button>
) : (
<Button variant="contained" onClick={handleAuth}>
Authenticate with AID
</Button>
)}
</p>
{storageToken ? null : (
<Button
id="login-btn"
Expand Down
17 changes: 7 additions & 10 deletions src/components/credentialCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ interface ICredential {

export function CredentialCard({ credential }: ICredential): JSX.Element {
return (
<div className="m-auto max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow text-gray-900">
<div className="mb-2 flex flex-row justify-between">
<div className="m-auto max-w-sm px-4 py-2 bg-white border border-gray-200 rounded-lg shadow text-gray-900">
<div className="flex flex-row justify-between">
<div>
<p className="font-bold text-lg text-gray-dark">
{credential.schema.title}
</p>
<p className="font-bold text-gray-dark">{credential.schema.title}</p>
<p className="font-normal text-md text-gray">
{credential.schema.credentialType}
</p>
Expand All @@ -29,16 +27,15 @@ export function CredentialCard({ credential }: ICredential): JSX.Element {
/>
</svg>
</div>

<div className="mb-2">
{/* <p className="font-bold text-lg text-gray-dark">Name</p> */}
<div className="">
<p className="font-normal text-md text-gray">
{credential.schema.description}
</p>
</div>
<div className="mb-2 flex flex-row justify-between">
<div className="flex flex-row justify-between">
<div className="">
<p className="font-bold text-gray text-lg">November 08, 2023</p>
<p className="font-bold text-gray-dark">Last Used: </p>
<p className="font-normal text-gray">November 08, 2023</p>
</div>
{credential.status?.et === "iss" ? (
<div className="flex flex-col items-center text-green">
Expand Down
5 changes: 5 additions & 0 deletions src/components/credentialList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export function CredentialList(): JSX.Element {
<CredentialCard credential={credential} />
</div>
))}
{!isLoading && !credentials?.length ? (
<p className="">No items to show</p>
) : (
<></>
)}
</>
);
}
8 changes: 4 additions & 4 deletions src/components/customRadio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export function CustomRadio({
return (
<div
onClick={onClick}
className={`flex cursor-pointer items-center border ${
checked ? "border-green" : ""
className={`flex cursor-pointer items-center border rounded ${
checked ? "border-green bg-green" : ""
}`}
>
<input
Expand All @@ -24,9 +24,9 @@ export function CustomRadio({
type="radio"
value=""
name="bordered-radio"
className="w-4 h-4 dark:ring-offset-green "
className="w-4 h-4 accent-green"
/>
<label htmlFor={id} className="w-full ms-1 font-medium">
<label htmlFor={id} className="cursor-pointer w-full ms-1 font-medium">
{component}
</label>
</div>
Expand Down
27 changes: 14 additions & 13 deletions src/components/identifierCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ interface IIdentifier {}

export function IdentifierCard({ aid }): JSX.Element {
return (
<div className="m-auto max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow text-gray-900">
<div className="mb-3 flex flex-row justify-between">
<div className="m-auto max-w-sm px-4 py-2 bg-white border border-gray-200 rounded-lg shadow text-gray-900">
<div className="flex flex-row justify-between">
<div>
<p className=" mb-1 font-bold text-gray-dark">Alias:</p>
<p className="font-normal text-gray">{aid.name}</p>
<p className="font-bold text-gray-dark">
Alias:{" "}
<span className="font-normal text-gray max-w">{aid.name}</span>
</p>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -23,20 +25,19 @@ export function IdentifierCard({ aid }): JSX.Element {
/>
</svg>
</div>

<div className="mb-3">
<p className=" mb-1 font-bold text-gray-dark">ID:</p>
<p className="font-normal text-gray">{aid.prefix}</p>
<div className="">
<p className="font-bold text-gray-dark">ID:</p>
<p className="font-normal text-gray max-w-[200px] break-words">
{aid.prefix}
</p>
</div>
<div className="mb-3 flex flex-row justify-between">
<div className="flex flex-row justify-between">
<div className="">
<p className=" mb-1 font-bold text-gray-dark">
Credentials Received:
</p>
<p className="font-bold text-gray-dark">Credentials Received: </p>
<p className="font-normal text-gray">13</p>
</div>
<div className="">
<p className=" mb-1 font-bold text-gray-dark">Last Used:</p>
<p className="font-bold text-gray-dark">Last Used: </p>
<p className="font-normal text-gray">November 08, 2023</p>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions src/components/identifierList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export function IdentifierList(): JSX.Element {
<IdentifierCard aid={aid} />
</div>
))}
{!isLoading && !aids?.length ? (
<p className="">No items to show</p>
) : (
<></>
)}
</>
);
}
19 changes: 14 additions & 5 deletions src/components/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import { Sidebar } from "@components/sidebar";
import { SelectIdentifier } from "@components/selectIdentifier";
import { SelectCredential } from "@components/selectCredential";
import { APP_STATE } from "@pages/popup/constants";
import { IdentifierList } from "@components/identifierList";
import { CredentialList } from "@components/credentialList";
Expand All @@ -25,6 +26,16 @@ export function Main(props: IMain): JSX.Element {

if (data?.appState) {
setTabState(data?.appState);
if (
data?.appState === APP_STATE.SELECT_IDENTIFIER ||
data?.appState === APP_STATE.SELECT_CREDENTIAL
) {
setActiveSidebar(
data?.appState === APP_STATE.SELECT_IDENTIFIER
? "Identifiers"
: "Credentials"
);
}
}
};

Expand All @@ -35,7 +46,7 @@ export function Main(props: IMain): JSX.Element {
const renderItems = () => {
if (tabState === APP_STATE.SELECT_IDENTIFIER) return <SelectIdentifier />;

if (tabState === APP_STATE.SELECT_CREDENTIAL) return <SelectIdentifier />;
if (tabState === APP_STATE.SELECT_CREDENTIAL) return <SelectCredential />;

switch (activeSidebar) {
case "Credentials":
Expand All @@ -56,7 +67,7 @@ export function Main(props: IMain): JSX.Element {
};

return (
<main className="">
<main className="w-[640px]">
<Sidebar
active={activeSidebar}
onClickLink={setActiveSidebar}
Expand All @@ -66,9 +77,7 @@ export function Main(props: IMain): JSX.Element {
<div className="rounded p-2 sm:ml-48 sm:mt-4 bg-gray-dark text-gray-light mr-4">
<div className="">
<p className="text-xl capitalize font-bold">{activeSidebar}</p>
<div className="bg-black py-8 rounded-3xl m-5 max-h-[576px] overflow-auto">
{renderItems()}
</div>
<div className="m-5 max-h-[576px] overflow-auto">{renderItems()}</div>
</div>
</div>
</main>
Expand Down
66 changes: 66 additions & 0 deletions src/components/selectCredential.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState, useEffect } from "react";
import { CustomRadio } from "@components/customRadio";
import { CredentialCard } from "@components/credentialCard";
import { IMessage } from "@pages/background/types";
import { APP_STATE } from "@pages/popup/constants";

export function SelectCredential(): JSX.Element {
const [credentials, setCredentials] = useState([]);
const [selectedCredential, setSelectedCredential] = useState(null);

const fetchCredentials = async () => {
const { data } = await chrome.runtime.sendMessage<IMessage<void>>({
type: "fetch-resource",
subtype: "credentials",
});
setCredentials(data.credentials);
};

const createSigninWithCredential = async () => {
const { data } = await chrome.runtime.sendMessage<IMessage<void>>({
type: "create-resource",
subtype: "signin",
data: {
credential: selectedCredential,
},
});
await chrome.runtime.sendMessage({
type: "tab",
subtype: "set-app-state",
data: {
appState: APP_STATE.DEFAULT,
},
});
window.close();
};

useEffect(() => {
fetchCredentials();
}, []);

return (
<>
{credentials.map((credential, index) => (
<div key={index} className="my-2 mx-4">
<CustomRadio
id={credential?.schema?.title}
checked={
selectedCredential?.schema?.title === credential?.schema?.title
}
onClick={() => setSelectedCredential(credential)}
component={<CredentialCard credential={credential} />}
/>
</div>
))}
<button
disabled={!selectedCredential}
onClick={createSigninWithCredential}
className={`fixed bottom-0 right-4 text-white ${
selectedCredential ? "bg-green" : " bg-gray"
} focus:outline-none font-medium rounded-full text-sm px-5 py-2.5 text-center me-2 mb-2`}
>
Select
</button>
</>
);
}
14 changes: 8 additions & 6 deletions src/components/selectIdentifier.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,20 @@ export function SelectIdentifier(): JSX.Element {
});
await chrome.runtime.sendMessage({
type: "tab",
subtype: "set-tab-state",
subtype: "set-app-state",
data: {
appState: APP_STATE.DEFAULT,
},
});

console.log("data.signins", data.signins);
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {type:"tab", subtype: "reload-state"}, function(response){

});
});
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(
tabs[0].id,
{ type: "tab", subtype: "reload-state" },
function (response) {}
);
});
window.close();
};

Expand Down
14 changes: 7 additions & 7 deletions src/components/signinCard.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export function SigninCard({ signin }): JSX.Element {
return (
<div className="m-auto max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow text-gray-900">
<div className="mb-2 flex flex-row justify-between">
<div className="m-auto max-w-sm px-4 py-2 bg-white border border-gray-200 rounded-lg shadow text-gray-900">
<div className="flex flex-row justify-between">
<div>
<p className="font-bold text-lg text-gray-dark">Website</p>
<p className="font-bold text-gray-dark">Website</p>
<p className="font-normal text-md text-gray">{signin?.domain}</p>
</div>
<svg
Expand All @@ -22,16 +22,16 @@ export function SigninCard({ signin }): JSX.Element {
</svg>
</div>

<div className="mb-2">
<p className="font-bold text-lg text-gray-dark">
<div className="">
<p className="font-bold text-gray-dark">
{signin?.identifier ? "Identifier Alias" : "Credential"}
</p>
<p className="font-normal text-md text-gray">
{signin?.identifier?.name}
</p>
</div>
<div className="mb-1">
<p className="font-bold text-lg text-gray-dark">Last Used</p>
<div className="">
<p className="font-bold text-gray-dark">Last Used</p>
<p className="font-normal text-md text-gray">
{new Date(signin?.updatedAt).toDateString()}
</p>
Expand Down
5 changes: 5 additions & 0 deletions src/components/signinList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export function SigninList(): JSX.Element {
<SigninCard signin={signin} />
</div>
))}
{!isLoading && !signins?.length ? (
<p className="">No items to show</p>
) : (
<></>
)}
</>
);
}
Loading