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 chrome storage service #32

Merged
merged 6 commits into from
Dec 26, 2023
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
3 changes: 2 additions & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"128": "public/128_keri_logo.png"
},
"permissions": [
"activeTab"
"activeTab",
"storage"
],
"content_scripts": [
{
Expand Down
80 changes: 80 additions & 0 deletions src/components/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { userService } from "@pages/background/services/user";

interface IMain {
handleSignout: () => void;
}

export function Main(props: IMain): JSX.Element {
return (
<main>
<aside
id="default-sidebar"
className="fixed top-0 left-0 z-40 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0"
aria-label="Sidebar"
>
<div className="h-full px-3 py-4 overflow-y-auto bg-gray-50 dark:bg-gray-800">
<ul className="space-y-2 font-medium">
<li>
<a
href="#"
className="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group"
>
<svg
className="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 22 21"
>
<path d="M16.975 11H10V4.025a1 1 0 0 0-1.066-.998 8.5 8.5 0 1 0 9.039 9.039.999.999 0 0 0-1-1.066h.002Z" />
<path d="M12.5 0c-.157 0-.311.01-.565.027A1 1 0 0 0 11 1.02V10h8.975a1 1 0 0 0 1-.935c.013-.188.028-.374.028-.565A8.51 8.51 0 0 0 12.5 0Z" />
</svg>
<span className="ms-3">Identifiers</span>
</a>
</li>
<li>
<a
href="#"
className="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group"
>
<svg
className="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 18 18"
>
<path d="M6.143 0H1.857A1.857 1.857 0 0 0 0 1.857v4.286C0 7.169.831 8 1.857 8h4.286A1.857 1.857 0 0 0 8 6.143V1.857A1.857 1.857 0 0 0 6.143 0Zm10 0h-4.286A1.857 1.857 0 0 0 10 1.857v4.286C10 7.169 10.831 8 11.857 8h4.286A1.857 1.857 0 0 0 18 6.143V1.857A1.857 1.857 0 0 0 16.143 0Zm-10 10H1.857A1.857 1.857 0 0 0 0 11.857v4.286C0 17.169.831 18 1.857 18h4.286A1.857 1.857 0 0 0 8 16.143v-4.286A1.857 1.857 0 0 0 6.143 10Zm10 0h-4.286A1.857 1.857 0 0 0 10 11.857v4.286c0 1.026.831 1.857 1.857 1.857h4.286A1.857 1.857 0 0 0 18 16.143v-4.286A1.857 1.857 0 0 0 16.143 10Z" />
</svg>
<span className="ms-3 whitespace-nowrap">Credentials</span>
</a>
</li>
<li>
<a
href="#"
className="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group"
>
<svg
className="flex-shrink-0 w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 20"
>
<path d="m17.418 3.623-.018-.008a6.713 6.713 0 0 0-2.4-.569V2h1a1 1 0 1 0 0-2h-2a1 1 0 0 0-1 1v2H9.89A6.977 6.977 0 0 1 12 8v5h-2V8A5 5 0 1 0 0 8v6a1 1 0 0 0 1 1h8v4a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-4h6a1 1 0 0 0 1-1V8a5 5 0 0 0-2.582-4.377ZM6 12H4a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2Z" />
</svg>
<span className="ms-3 whitespace-nowrap">Sign in</span>
</a>
</li>
</ul>
</div>
</aside>
<div className="p-4 sm:ml-64">
<button onClick={props.handleSignout}>Logout</button>
<div className="p-4 border-2 border-gray-200 border-dashed rounded-lg dark:border-gray-700">
<div className="grid grid-cols-3 gap-4 mb-4">Hello World</div>
</div>
</div>
</main>
);
}
77 changes: 77 additions & 0 deletions src/components/signin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useState } from "react";
import logo from "@assets/img/128_keri_logo.png";

interface ISignin {
vendorUrl?: string;
passcode?: string;
handleConnect: (vendorUrl?: string, passcode?: string) => void;
}

export function Signin(props: ISignin): JSX.Element {
const [vendorUrl, setVendorUrl] = useState("");
const [passcode, setPasscode] = useState("");

return (
<div className="grid grid-cols-1 gap-2">
<div className="flex flex-row justify-between">
<p>KERI</p>
<div>Settings Icons</div>
</div>
<div className="flex flex-row justify-center">
<img src={logo} className="w-32 h-32" alt="logo" />
</div>
<div>
<input
type="text"
id="vendor_url"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Enter Keria url"
required
onChange={(e) => setVendorUrl(e.target.value)}
/>
</div>
<div>
<input
type="password"
id="passcode"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Enter your passcode"
required
onChange={(e) => setPasscode(e.target.value)}
/>
</div>
<div>
<button
type="button"
onClick={() => props.handleConnect(vendorUrl, passcode)}
className="text-white bg-green-700 hover:bg-green-800 focus:outline-none focus:ring-4 focus:ring-green-300 font-medium rounded-full text-sm px-5 py-2.5 text-center me-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
>
Connect
</button>
</div>
<div>
<a
href="#"
className="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>
Don't have account?
</a>
</div>
<div className="flex flex-row justify-center">
<a
href="#"
className="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>
docs
</a>
<strong>|</strong>
<a
href="#"
className="font-medium text-blue-600 dark:text-blue-500 hover:underline"
>
support
</a>
</div>
</div>
);
}
97 changes: 60 additions & 37 deletions src/pages/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,66 @@
import { randomPasscode, SignifyClient, Tier, ready } from 'signify-ts'
const url = "https://keria-dev.rootsid.cloud/admin"
const boot_url = "https://keria-dev.rootsid.cloud"
import { userService } from "@pages/background/services/user";
import { configService } from "@pages/background/services/config";
import { senderIsPopup } from "@pages/background/utils";

console.log('Background script loaded');
console.log("Background script loaded");

// Handle messages
chrome.runtime.onMessage.addListener(
async function (message, sender, sendResponse) {
if (sender.tab) {
// Handle mesages from content script
console.log("Message received from content script at " + sender.tab.url + ": " + message.type)
if (message.type) {
switch (message.type) {
case "getVersion":
const manifestData = chrome.runtime.getManifest()
sendResponse(manifestData.version);
break;
case "isUnlocked":
const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});
const response = chrome.tabs.sendMessage(tab.id!, {type: "for_content_script"});
// sendResponse(true);
break;
case "hasLogin":
sendResponse({ login: "AID 123" });
break;
case "authenticate":
sendResponse({ signature: "ABCD" });
break;
default:
break;
}
}
export interface IMessage<T> {
type: string
subtype?: string
data: T
}

} else if (sender.origin === "chrome-extension://" + chrome.runtime.id &&
sender.url === "chrome-extension://" + chrome.runtime.id + "/src/pages/popup/index.html") {
// handle messages from Popup
console.log("Message received from browser extension pupup: " + message)
sendResponse({ resp: "received" });
// Handle messages
chrome.runtime.onMessage.addListener(function (message: IMessage<any>, sender, sendResponse) {
(async () => {
if (sender.tab) {
// Handle mesages from content script
console.log(
"Message received from content script at " +
sender.tab.url +
": " +
message.type
);
if (message.type) {
switch (message.type) {
case "getVersion":
const manifestData = chrome.runtime.getManifest();
sendResponse(manifestData.version);
break;
case "isUnlocked":
const [tab] = await chrome.tabs.query({
active: true,
lastFocusedWindow: true,
});
const response = chrome.tabs.sendMessage(tab.id!, {
type: "for_content_script",
});
// sendResponse(true);
break;
case "hasLogin":
sendResponse({ login: "AID 123" });
break;
case "authenticate":
sendResponse({ signature: "ABCD" });
break;
default:
break;
}
}
} else if (senderIsPopup(sender)) {
// handle messages from Popup
console.log("Message received from browser extension pupup: " + message);
if (
message.type === "authentication" &&
message.subtype === "persist-token"
) {
await userService.setToken(message.data.passcode);
await configService.setUrl(message.data.vendorUrl);
}
sendResponse({ resp: "received" });
}
);
})();

// return true to indicate chrome api to send a response asynchronously
return true;
});
48 changes: 48 additions & 0 deletions src/pages/background/services/browser-storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
export const getSyncStorage = () => {
return chrome.storage.sync;
}

export const getNonSyncStorage = () => {
return chrome.storage.local;
}

const BrowserStorage = (storage = getNonSyncStorage()) => {
const _storage = storage;

const getAllKeys = () => {
return new Promise(resolve => {
_storage.get(null, allItems => {
resolve(Object.keys(allItems));
});
});
}

const getValue = (name) => {
return new Promise(resolve => {
_storage.get(name, items => {
resolve(items[name]);
});
});
}

const removeKey = (name) => {
return new Promise<void>(resolve => {
_storage.remove(name, () => resolve());
});
}

const setValue = (name, value) => {
return new Promise<void>(resolve => {
_storage.set({ [name]: value }, () => resolve());
});
}

return {
getAllKeys,
getValue,
removeKey,
setValue
}
}

export const browserStorageService = BrowserStorage()
27 changes: 27 additions & 0 deletions src/pages/background/services/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { browserStorageService } from "@pages/background/services/browser-storage"

const CONFIG_ENUMS = {
VENDOR_URL: "vendor-url"
}

const Config = () => {
const getUrl = async () => {
return await browserStorageService.getValue(CONFIG_ENUMS.VENDOR_URL);
}

const removeUrl = async () => {
await browserStorageService.removeKey(CONFIG_ENUMS.VENDOR_URL);
}

const setUrl = async (token: string) => {
await browserStorageService.setValue(CONFIG_ENUMS.VENDOR_URL, token)
}

return {
setUrl,
removeUrl,
getUrl
}
}

export const configService = Config()
27 changes: 27 additions & 0 deletions src/pages/background/services/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { browserStorageService } from "@pages/background/services/browser-storage"

const USER_ENUMS = {
TOKEN: "user-token"
}

const User = () => {
const getToken = async () => {
return await browserStorageService.getValue(USER_ENUMS.TOKEN);
}

const removeToken = async () => {
await browserStorageService.removeKey(USER_ENUMS.TOKEN);
}

const setToken = async (token: string) => {
await browserStorageService.setValue(USER_ENUMS.TOKEN, token)
}

return {
removeToken,
getToken,
setToken
}
}

export const userService = User()
5 changes: 5 additions & 0 deletions src/pages/background/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const senderIsPopup = (sender: chrome.runtime.MessageSender) => {
const origin = "chrome-extension://" + chrome.runtime.id;
const popupPath = origin + "/src/pages/popup/index.html";
return sender.origin === origin && sender.url === popupPath;
};
Loading