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/agent onboarding #142

Merged
merged 4 commits into from
Mar 19, 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
9 changes: 9 additions & 0 deletions example-web/my-app/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function CircularIndeterminate() {
);
}

const ROOTSID_URL = "https://api.npoint.io/52639f849bb31823a8c0";
const PROVENANT_URL = "https://api.npoint.io/d59bd3ab0b31de863a20";
const FACEBOOK_URL = "https://api.npoint.io/1d388b8942c4ec3ed763";
const GITHUB_URL = "https://api.npoint.io/a75a0383d2820a2153c1";
Expand Down Expand Up @@ -91,13 +92,21 @@ function App() {
<div
style={{ display: "flex", flexDirection: "column", rowGap: "8px" }}
>
<p className="auth-heading">Request Permissions</p>
<Button
variant="contained"
color="success"
onClick={() => handleSettingVendorUrl(PROVENANT_URL)}
>
Provenant Theme (has Agent)
</Button>
<Button
variant="contained"
color="success"
onClick={() => handleSettingVendorUrl(ROOTSID_URL)}
>
RootsID Theme
</Button>
<Button
variant="contained"
color="success"
Expand Down
8 changes: 7 additions & 1 deletion src/_locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,11 @@
"signin.requestAuth": "requests authentication with",
"signin.website": "Website",
"signin.with": "Sign in with",
"signins.title": "Sign Ins"
"signins.title": "Sign Ins",
"signup.action.copyToClipboard": "Copy to clipboard!",
"signup.desc.safegaurd": "The passcode safeguards your identity.",
"signup.desc.storeYourPasscode": "Please store it in a secure online or offline location.",
"signup.title.generatePasscode": "Generate Passcode",
"signup.title.saveYourPasscode": "Save your Passcode",
"signup.warning.cannotRetrieve": "We CANNOT retrieve your passcode if you lose it."
}
8 changes: 7 additions & 1 deletion src/_locales/es-419.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,11 @@
"signin.requestAuth": "solicita autenticación con",
"signin.website": "Sitio web",
"signin.with": "Ingresar con",
"signins.title": "Ingresar"
"signins.title": "Ingresar",
"signup.action.copyToClipboard": "¡Copiar al portapapeles!",
"signup.desc.safegaurd": "El código de acceso protege su identidad.",
"signup.desc.storeYourPasscode": "Guárdelo en una ubicación segura en línea o fuera de línea.",
"signup.title.generatePasscode": "Generar contraseña",
"signup.title.saveYourPasscode": "Guarde su contraseña",
"signup.warning.cannotRetrieve": "NO PODEMOS recuperar su contraseña si la pierde."
}
8 changes: 7 additions & 1 deletion src/_locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,11 @@
"signin.requestAuth": "solicita autenticación con",
"signin.website": "Sitio web",
"signin.with": "Ingresar con",
"signins.title": "Ingresar"
"signins.title": "Ingresar",
"signup.action.copyToClipboard": "¡Copiar al portapapeles!",
"signup.desc.safegaurd": "El código de acceso protege su identidad.",
"signup.desc.storeYourPasscode": "Guárdelo en una ubicación segura en línea o fuera de línea.",
"signup.title.generatePasscode": "Generar contraseña",
"signup.title.saveYourPasscode": "Guarde su contraseña",
"signup.warning.cannotRetrieve": "NO PODEMOS recuperar su contraseña si la pierde."
}
4 changes: 2 additions & 2 deletions src/_locales/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import es_419 from "@src/_locales/es-419.json";
const existingLanguageCodes = ["en", "es", "es-419"];
export const languageCodeMap = {
en: "English",
es: "Spanish",
"es-419": "Spanish (LA)",
es: "Español",
"es-419": "Español (LA)",
};

export * from "./localeContext";
Expand Down
31 changes: 31 additions & 0 deletions src/components/shared/icons/eye-off.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export default function EyeOff({ className }: { className?: string }) {
return (
<svg
className={className}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.4955 7.44088C3.54724 8.11787 2.77843 8.84176 2.1893 9.47978C0.857392 10.9222 0.857393 13.0778 2.1893 14.5202C3.9167 16.391 7.18879 19 12 19C13.2958 19 14.4799 18.8108 15.5523 18.4977L13.8895 16.8349C13.2936 16.9409 12.6638 17 12 17C7.9669 17 5.18832 14.82 3.65868 13.1634C3.03426 12.4872 3.03426 11.5128 3.65868 10.8366C4.23754 10.2097 4.99526 9.50784 5.93214 8.87753L4.4955 7.44088Z"
fill="currentColor"
/>
<path
d="M8.53299 11.4784C8.50756 11.6486 8.49439 11.8227 8.49439 12C8.49439 13.933 10.0614 15.5 11.9944 15.5C12.1716 15.5 12.3458 15.4868 12.516 15.4614L8.53299 11.4784Z"
fill="currentColor"
/>
<path
d="M15.4661 12.4471L11.5473 8.52829C11.6937 8.50962 11.8429 8.5 11.9944 8.5C13.9274 8.5 15.4944 10.067 15.4944 12C15.4944 12.1515 15.4848 12.3007 15.4661 12.4471Z"
fill="currentColor"
/>
<path
d="M18.1118 15.0928C19.0284 14.4702 19.7715 13.7805 20.3413 13.1634C20.9657 12.4872 20.9657 11.5128 20.3413 10.8366C18.8117 9.18002 16.0331 7 12 7C11.3594 7 10.7505 7.05499 10.1732 7.15415L8.50483 5.48582C9.5621 5.1826 10.7272 5 12 5C16.8112 5 20.0833 7.60905 21.8107 9.47978C23.1426 10.9222 23.1426 13.0778 21.8107 14.5202C21.2305 15.1486 20.476 15.8603 19.5474 16.5284L18.1118 15.0928Z"
fill="currentColor"
/>
<path
d="M2.00789 3.42207C1.61736 3.03155 1.61736 2.39838 2.00789 2.00786C2.39841 1.61733 3.03158 1.61733 3.4221 2.00786L22.0004 20.5862C22.391 20.9767 22.391 21.6099 22.0004 22.0004C21.6099 22.3909 20.9767 22.3909 20.5862 22.0004L2.00789 3.42207Z"
fill="currentColor"
/>
</svg>
);
}
25 changes: 25 additions & 0 deletions src/components/shared/icons/eye.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export default function Eye({ className }: { className?: string }) {
return (
<svg
className={className}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.0007 12C15.0007 13.6569 13.6576 15 12.0007 15C10.3439 15 9.00073 13.6569 9.00073 12C9.00073 10.3431 10.3439 9 12.0007 9C13.6576 9 15.0007 10.3431 15.0007 12Z"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12.0012 5C7.52354 5 3.73326 7.94288 2.45898 12C3.73324 16.0571 7.52354 19 12.0012 19C16.4788 19 20.2691 16.0571 21.5434 12C20.2691 7.94291 16.4788 5 12.0012 5Z"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
}
30 changes: 30 additions & 0 deletions src/pages/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,36 @@ chrome.runtime.onMessage.addListener(function (
sendResponse({ data: { success: true } });
}
}

if (
message.type === "authentication" &&
message.subtype === "boot-and-connect-agent"
) {
const resp = (await signifyService.bootAndConnect(
message.data.agentUrl,
message.data.bootUrl,
message.data.passcode
)) as any;
if (resp?.error) {
sendResponse({
error: {
code: 404,
message: resp?.error?.message,
},
});
} else {
await userService.setPasscode(message.data.passcode);
sendResponse({ data: { success: true } });
}
}

if (
message.type === "authentication" &&
message.subtype === "generate-passcode"
) {
const passcode = signifyService.generatePasscode();
sendResponse({ data: { passcode } });
}
}

if (message.type === "create-resource" && message.subtype === "signin") {
Expand Down
7 changes: 7 additions & 0 deletions src/pages/background/services/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ const Config = () => {
await browserStorageService.setValue(CONFIG_ENUMS.AGENT_URL, token);
};

const getHasOnboarded = async () => {
return (await browserStorageService.getValue(
CONFIG_ENUMS.HAS_ONBOARDED
)) as boolean;
};

const setHasOnboarded = async (value: boolean) => {
await browserStorageService.setValue(CONFIG_ENUMS.HAS_ONBOARDED, value);
};
Expand Down Expand Up @@ -115,6 +121,7 @@ const Config = () => {
setLanguage,
getAgentUrl,
setAgentUrl,
getHasOnboarded,
setHasOnboarded,
getAgentAndVendorInfo,
setWebRequestedPermission,
Expand Down
2 changes: 2 additions & 0 deletions src/pages/background/services/signify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ const Signify = () => {
listCredentials,
signHeaders,
createAID,
generatePasscode,
bootAndConnect,
};
};

Expand Down
49 changes: 49 additions & 0 deletions src/pages/popup/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import {
WEB_APP_PERMS,
configService,
} from "@pages/background/services/config";
import { isValidUrl } from "@pages/background/utils";
import { ThemeProvider, styled } from "styled-components";
import { LocaleProvider } from "@src/_locales";
import { default as defaultVendor } from "@src/config/vendor.json";
import { IVendorData, IMessage } from "@config/types";
import { Permission } from "@src/screens/permission";
import { Signin } from "@src/screens/signin";
import { Signup } from "@src/screens/signup";
import { Loader } from "@components/ui";
import { Main } from "@components/main";

interface IBootAndConnect {
passcode?: string;
agentUrl?: string;
bootUrl: string;
}

interface IConnect {
passcode?: string;
agentUrl?: string;
Expand All @@ -35,6 +43,7 @@ const StyledLoader = styled.div`
export default function Popup(): JSX.Element {
const [vendorData, setVendorData] = useState<IVendorData>(defaultVendor);
const [showConfig, setShowConfig] = useState(false);
const [showSignup, setShowSignup] = useState(false);

const [permissionData, setPermissionData] = useState(false);
const [isConnected, setIsConnected] = useState(false);
Expand Down Expand Up @@ -101,6 +110,37 @@ export default function Popup(): JSX.Element {
checkInitialConnection();
}, []);

const handleBootAndConnect = async (passcode: string) => {
const agentUrl = await configService.getAgentUrl();
const urlObject = isValidUrl(agentUrl);

if (!urlObject || !urlObject?.origin) return;
setIsLoading(true);

const { data, error } = await chrome.runtime.sendMessage<
IMessage<IBootAndConnect>
>({
type: "authentication",
subtype: "boot-and-connect-agent",
data: {
passcode,
agentUrl,
bootUrl: urlObject.origin,
},
});

setIsLoading(false);
if (error) {
setConnectError(error?.message);
setTimeout(() => {
setConnectError("");
}, 3000);
} else {
setShowSignup(false);
await checkConnection();
}
};

const handleConnect = async (passcode: string) => {
setIsLoading(true);
const agentUrl = await configService.getAgentUrl();
Expand Down Expand Up @@ -170,6 +210,14 @@ export default function Popup(): JSX.Element {
handleDisconnect={handleDisconnectPermission}
/>
</div>
) : showSignup ? (
<div className="w-[300px]">
<Signup
isLoading={isLoading}
handleBootAndConnect={handleBootAndConnect}
signupError={connectError}
/>
</div>
) : (
<>
{isConnected ? (
Expand All @@ -190,6 +238,7 @@ export default function Popup(): JSX.Element {
vendorData={vendorData}
showConfig={showConfig}
setShowConfig={setShowConfig}
handleSignup={() => setShowSignup(true)}
/>
</div>
)}
Expand Down
37 changes: 27 additions & 10 deletions src/screens/signin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useState, useEffect } from "react";
import { useIntl } from "react-intl";
import { Text } from "@components/ui";
import { configService } from "@pages/background/services/config";
import { Config } from "@src/screens/config";
import { IVendorData } from "@config/types";
import { Signin as SigninComponent } from "./signin";
Expand All @@ -16,10 +18,21 @@ interface ISignin {
afterSetUrl?: () => void;
showConfig: boolean;
setShowConfig: (state: boolean) => void;
handleSignup: () => void;
}

export function Signin(props: ISignin): JSX.Element {
const { formatMessage } = useIntl();
const [hasOnboarded, setHasOnboarded] = useState(false);

const checkIfOnboarded = async () => {
const _hasOnboarded = await configService.getHasOnboarded();
setHasOnboarded(_hasOnboarded);
};

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

return (
<div className="grid grid-cols-1 gap-2">
Expand Down Expand Up @@ -53,7 +66,10 @@ export function Signin(props: ISignin): JSX.Element {
</div>
{props.showConfig ? (
<Config
handleBack={() => props.setShowConfig(false)}
handleBack={() => {
props.setShowConfig(false);
checkIfOnboarded();
}}
afterSetUrl={props?.afterSetUrl}
/>
) : (
Expand All @@ -65,15 +81,16 @@ export function Signin(props: ISignin): JSX.Element {
/>
)}
<div className="text-xs absolute bottom-2 w-full">
<div className=" text-center">
<a
href={props?.vendorData?.onboardingUrl}
className="font-medium hover:underline"
target="_blank"
>
{formatMessage({ id: "account.onboard.cta" })}
</a>
</div>
{hasOnboarded ? (
<div className=" text-center">
<button
onClick={props.handleSignup}
className="font-medium hover:underline"
>
{formatMessage({ id: "account.onboard.cta" })}
</button>
</div>
) : null}
<div className=" text-center">
<a
href={props?.vendorData?.docsUrl}
Expand Down
1 change: 1 addition & 0 deletions src/screens/signup/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Signup } from "./signup";
Loading