From 2ce7cd86fc03422ec03065d3a6f9c1ccc1e052fb Mon Sep 17 00:00:00 2001 From: Aris Ripandi Date: Mon, 29 Aug 2022 18:11:47 +0700 Subject: [PATCH 1/5] change TOTP generator library using otpauth npm synchronous --- apps/desktop/src/mocks.ts | 45 ------------------------ apps/desktop/src/utils/array-helpers.ts | 4 ++- apps/desktop/src/utils/string-helpers.ts | 11 ++++-- package.json | 16 ++++----- pnpm-lock.yaml | 19 ++++++---- 5 files changed, 32 insertions(+), 63 deletions(-) delete mode 100644 apps/desktop/src/mocks.ts diff --git a/apps/desktop/src/mocks.ts b/apps/desktop/src/mocks.ts deleted file mode 100644 index 1275fa2..0000000 --- a/apps/desktop/src/mocks.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { faker } from '@faker-js/faker' -import { sortObjectsByProp, groupArrayObjectByAlphabet } from './utils/array-helpers' -import { generateTOTP } from './utils/string-helpers' - -const generateMock = async (count: number): Promise => { - const result = [] - - for (let i = 0; i < count; i++) { - const id = faker.datatype.uuid() - const issuer = faker.internet.domainName() - const user_identity = faker.internet.email().toLowerCase() - const secret = faker.random.alphaNumeric(40) - const algorithm = 'SHA1' - const kind = 'TOTP' - const period = 30 - const digits = 6 - - // Create a new TOTP object. - const token = await generateTOTP({ secret, period, digits, algorithm }) - - result.push({ - id, - issuer, - user_identity, - token, - secret, - algorithm, - kind, - period, - digits, - }) - } - - return result -} - -// Unsorted mock data. -export const randomData = await generateMock(100) - -// Sort array with the custom function that sorts alphabetically by the name key -export const sortedData = sortObjectsByProp(randomData, 'issuer') - -// Group array by the alphabetical key of the name key -export const collectionGrouped = groupArrayObjectByAlphabet(sortedData) -// export const collectionGrouped = {} diff --git a/apps/desktop/src/utils/array-helpers.ts b/apps/desktop/src/utils/array-helpers.ts index 0249cea..7d82184 100644 --- a/apps/desktop/src/utils/array-helpers.ts +++ b/apps/desktop/src/utils/array-helpers.ts @@ -105,11 +105,13 @@ export async function parseCollections(data: any[]) { const icon_path = item.icon_path ? await decryptStr(item.icon_path) : null // Generate TOTP token - const token = await generateTOTP({ + const token = generateTOTP({ + issuer: item.issuer, secret: secret, period: item.period, digits: item.digits, algorithm: item.algorithm, + label: item.user_identity, }) const result = { diff --git a/apps/desktop/src/utils/string-helpers.ts b/apps/desktop/src/utils/string-helpers.ts index faeea29..0499878 100644 --- a/apps/desktop/src/utils/string-helpers.ts +++ b/apps/desktop/src/utils/string-helpers.ts @@ -1,7 +1,10 @@ +import * as OTPAuth from 'otpauth' import { invoke } from '@tauri-apps/api/tauri' import { localData } from './storage' type GenerateTOTPTypes = { + label: string + issuer: string secret: string digits: number period: number @@ -50,6 +53,7 @@ export const decryptStr = async (encryptedStr: string): Promise => { export const md5Hash = async (str: string): Promise => { return invoke('md5_hash', { str }) } + export const createHash = async (plaintext: string): Promise => { return invoke('create_hash', { plaintext }) } @@ -60,6 +64,9 @@ export const verifyHash = async (plaintext: string, hashedStr: string): Promise< // Generate TOTP token from secret using Rust. // https://tauri.app/v1/guides/features/command/ -export const generateTOTP = async ({ secret, period, digits, algorithm }: GenerateTOTPTypes): Promise => { - return invoke('generate_totp', { secret, period, digits, algorithm }) +export const generateTOTP = ({ issuer, secret, period, digits, algorithm, label }: GenerateTOTPTypes): string => { + // return invoke('generate_totp', { secret, period, digits, algorithm }) + const totp = new OTPAuth.TOTP({ issuer, secret, period, digits, algorithm, label }) + + return totp.generate().toString() } diff --git a/package.json b/package.json index 2a3ef2b..6db1120 100755 --- a/package.json +++ b/package.json @@ -18,18 +18,18 @@ "clipboardy": "^3.0.0", "core-js": "^3.6.5", "inquirer": "^9.1.0", + "otpauth": "^8.0.2", + "react": "^18.2.0", "react-detect-offline": "^2.4.5", "react-dom": "^18.2.0", "react-hot-toast": "^2.3.0", "react-hotkeys-hook": "^3.4.7", - "react": "^18.2.0", "regenerator-runtime": "0.13.7", "tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#67530781d86b73fae4ee03c17f43c76f09ae3400", "tslib": "^2.4.0", "zustand": "^4.1.1" }, "devDependencies": { - "@faker-js/faker": "^7.4.0", "@fontsource/inter": "^4.5.12", "@nrwl/cli": "14.5.10", "@nrwl/eslint-plugin-nx": "14.5.10", @@ -50,36 +50,36 @@ "@types/inquirer": "^9.0.1", "@types/jest": "27.4.1", "@types/node": "18.7.13", + "@types/react": "^18.0.17", "@types/react-detect-offline": "^2.4.1", "@types/react-dom": "^18.0.6", - "@types/react": "^18.0.17", "@typescript-eslint/eslint-plugin": "^5.35.1", "@typescript-eslint/parser": "^5.35.1", "@vitejs/plugin-react": "^2.0.1", "babel-jest": "27.5.1", "clsx": "^1.2.1", "csstype": "^3.1.0", + "eslint": "~8.23.0", "eslint-config-prettier": "8.5.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-jsx-a11y": "6.6.1", - "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-react": "7.30.1", - "eslint": "~8.23.0", + "eslint-plugin-react-hooks": "4.6.0", "husky": "^8.0.1", "jest": "27.5.1", "lint-staged": "^13.0.3", "nx": "14.5.10", "postcss": "^8.4.16", - "prettier-plugin-tailwindcss": "^0.1.13", "prettier": "^2.7.1", + "prettier-plugin-tailwindcss": "^0.1.13", "react-test-renderer": "18.2.0", "tailwind-scrollbar-hide": "^1.1.7", "tailwindcss": "^3.1.8", "ts-jest": "27.1.4", "ts-node": "10.9.1", "typescript": "~4.7.4", - "vite-plugin-eslint": "1.8.1", - "vite": "^3.0.9" + "vite": "^3.0.9", + "vite-plugin-eslint": "1.8.1" }, "husky": { "hooks": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bb48bd..708b496 100755 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,7 +1,6 @@ lockfileVersion: 5.4 specifiers: - '@faker-js/faker': ^7.4.0 '@fontsource/inter': ^4.5.12 '@headlessui/react': ^1.6.6 '@heroicons/react': ^2.0.8 @@ -49,6 +48,7 @@ specifiers: jest: 27.5.1 lint-staged: ^13.0.3 nx: 14.5.10 + otpauth: ^8.0.2 postcss: ^8.4.16 prettier: ^2.7.1 prettier-plugin-tailwindcss: ^0.1.13 @@ -79,6 +79,7 @@ dependencies: clipboardy: 3.0.0 core-js: 3.25.0 inquirer: 9.1.0 + otpauth: 8.0.2 react: 18.2.0 react-detect-offline: 2.4.5 react-dom: 18.2.0_react@18.2.0 @@ -90,7 +91,6 @@ dependencies: zustand: 4.1.1_react@18.2.0 devDependencies: - '@faker-js/faker': 7.4.0 '@fontsource/inter': 4.5.12 '@nrwl/cli': 14.5.10 '@nrwl/eslint-plugin-nx': 14.5.10_mkfqjmeize2qesywaebju6tdq4 @@ -1558,11 +1558,6 @@ packages: - supports-color dev: true - /@faker-js/faker/7.4.0: - resolution: {integrity: sha512-xDd3Tvkt2jgkx1LkuwwxpNBy/Oe+LkZBTwkgEFTiWpVSZgQ5sc/LenbHKRHbFl0dq/KFeeq/szyyPtpJRKY0fg==} - engines: {node: '>=14.0.0', npm: '>=6.0.0'} - dev: true - /@fontsource/inter/4.5.12: resolution: {integrity: sha512-bGKk4/8tube/nCk8hav0ZDBVbzJzc7m0Vt4xF5p15IN4YImwGdtKG38Oq5bU8xHNS+VfvbFFCepgQNj7Pr/Lvg==} dev: true @@ -7606,6 +7601,10 @@ packages: graceful-fs: 4.2.10 dev: true + /jssha/3.2.0: + resolution: {integrity: sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==} + dev: false + /jsx-ast-utils/3.3.3: resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==} engines: {node: '>=4.0'} @@ -8411,6 +8410,12 @@ packages: engines: {node: '>=0.10.0'} dev: false + /otpauth/8.0.2: + resolution: {integrity: sha512-Hj5IvDdhte1dmjBkWZ3K8DfQVt4LQycd4mtRVyRTWtYiXuqaDSF4+d7UDPqZO/JRWXDktEmDHqymA+hHj9NEqQ==} + dependencies: + jssha: 3.2.0 + dev: false + /p-finally/1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} From a857db13f8d5d7253883648ba126ec6cb33bb018 Mon Sep 17 00:00:00 2001 From: Aris Ripandi Date: Tue, 30 Aug 2022 03:33:49 +0700 Subject: [PATCH 2/5] fix data fetch only when unlocked --- apps/desktop/src/components/AppMenu.tsx | 20 +++-------- apps/desktop/src/components/ConfirmDialog.tsx | 4 +-- apps/desktop/src/components/RefreshButton.tsx | 21 +++++++++++ apps/desktop/src/components/TitleBar.tsx | 2 +- apps/desktop/src/hooks/useGetCollections.ts | 4 +++ apps/desktop/src/hooks/useLoadCollections.ts | 36 ------------------- apps/desktop/src/screens/AuthScreen.tsx | 15 +++++--- apps/desktop/src/screens/ErrorScreen.tsx | 16 +++++---- apps/desktop/src/screens/MainScreen.tsx | 1 - apps/desktop/src/utils/string-helpers.ts | 2 +- libs/otentik-db/src/create-local-snapshot.ts | 2 +- .../src/create-production-snapshot.ts | 2 +- libs/otentik-db/src/restore-snapshot.ts | 8 ++--- 13 files changed, 60 insertions(+), 73 deletions(-) create mode 100644 apps/desktop/src/components/RefreshButton.tsx delete mode 100644 apps/desktop/src/hooks/useLoadCollections.ts diff --git a/apps/desktop/src/components/AppMenu.tsx b/apps/desktop/src/components/AppMenu.tsx index ea84a3a..6c5394c 100644 --- a/apps/desktop/src/components/AppMenu.tsx +++ b/apps/desktop/src/components/AppMenu.tsx @@ -1,7 +1,7 @@ import { Fragment } from 'react' import { appWindow } from '@tauri-apps/api/window' import { ask, open, save } from '@tauri-apps/api/dialog' -import { checkUpdate } from '@tauri-apps/api/updater' +// import { checkUpdate } from '@tauri-apps/api/updater' import { Menu, Transition } from '@headlessui/react' import { @@ -84,19 +84,9 @@ export const AppMenu = () => { const handleUpdate = async () => { try { - // const { shouldUpdate, manifest } = await checkUpdate() - const resp = await checkUpdate() - console.log('UPDATESSSSSSSS', resp) - - // if (shouldUpdate) { - // console.log('UPDATES', shouldUpdate) - // // display dialog - // await installUpdate() - // // install complete, restart app - // await relaunch() - // } + // TODO: enable auto update check } catch (error) { - console.log(error) + console.error(error) } } @@ -109,7 +99,7 @@ export const AppMenu = () => { useHotkeys('ctrl+l, command+l', () => setLockStreenState(true)) return ( -
+
@@ -125,7 +115,7 @@ export const AppMenu = () => { leaveFrom="transform opacity-100 scale-100" leaveTo="transform opacity-0 scale-95" > - + {!locked && ( <> diff --git a/apps/desktop/src/components/ConfirmDialog.tsx b/apps/desktop/src/components/ConfirmDialog.tsx index 9714d2e..ab2ad31 100644 --- a/apps/desktop/src/components/ConfirmDialog.tsx +++ b/apps/desktop/src/components/ConfirmDialog.tsx @@ -15,9 +15,7 @@ export const ConfirmDialog: FC = (props) => { const { children, open, onClose, title, onConfirm } = props const cancelButtonRef = useRef(null) - return !open ? ( - <> - ) : ( + return ( { + const setForceFetch = useStores((state) => state.setForceFetch) + + return ( +
+
+
+ +
+
+
+ ) +} diff --git a/apps/desktop/src/components/TitleBar.tsx b/apps/desktop/src/components/TitleBar.tsx index 76c0087..a9f3344 100644 --- a/apps/desktop/src/components/TitleBar.tsx +++ b/apps/desktop/src/components/TitleBar.tsx @@ -4,7 +4,7 @@ export const TitleBar = () => { return (
diff --git a/apps/desktop/src/hooks/useGetCollections.ts b/apps/desktop/src/hooks/useGetCollections.ts index dcc3c05..33b2f59 100644 --- a/apps/desktop/src/hooks/useGetCollections.ts +++ b/apps/desktop/src/hooks/useGetCollections.ts @@ -1,4 +1,5 @@ import { useQuery } from '@tanstack/react-query' +import { useStores } from '../stores/stores' import { parseCollections } from '../utils/array-helpers' import { localData } from '../utils/storage' @@ -10,6 +11,7 @@ type GetCollectionType = { } export const useGetCollections = ({ filter }: GetCollectionType) => { + const locked = useStores((state) => state.locked) const refreshTime = 30000 // How frequently you want to refresh the data, in ms // const user_id = useAuth()?.user?.id @@ -29,6 +31,8 @@ export const useGetCollections = ({ filter }: GetCollectionType) => { initialData: [], refetchInterval: refreshTime, // select: (data: any) => data.find((item: any) => item), + // Only fetch when screen unloced + enabled: !locked, } ) } diff --git a/apps/desktop/src/hooks/useLoadCollections.ts b/apps/desktop/src/hooks/useLoadCollections.ts deleted file mode 100644 index be9e2ba..0000000 --- a/apps/desktop/src/hooks/useLoadCollections.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { db as vaultDB, insert, search } from '../utils/lyra-search' -import { useGetCollections } from './useGetCollections' - -export const useLoadCollection = (filter: string) => { - const { isLoading, error, data: rawData, isFetching, refetch }: any = useGetCollections({}) - - let searchResult - if (rawData) { - // TODO: remove duplicates from existing search index. - rawData.map((item: any) => { - insert(vaultDB, { - collection_id: item.id, - algorithm: item.algorithm, - digits: item.digits, - issuer: item.issuer, - kind: item.kind, - period: item.period, - secret: item.secret, - token: item.token, - user_identity: item.user_identity, - }) - }) - - const { hits } = search(vaultDB, { - properties: ['issuer', 'user_identity'], - term: filter, - }) - - searchResult = hits - } - - // If no filter defined then return the fetched data. - const data = (filter || filter.length >= 1) && searchResult ? searchResult : rawData - - return { isLoading, error, data, isFetching, refetch } -} diff --git a/apps/desktop/src/screens/AuthScreen.tsx b/apps/desktop/src/screens/AuthScreen.tsx index d3fd94b..3be87ac 100644 --- a/apps/desktop/src/screens/AuthScreen.tsx +++ b/apps/desktop/src/screens/AuthScreen.tsx @@ -5,9 +5,10 @@ import toast from 'react-hot-toast' import { sbClient } from '../utils/supabase' import { LoaderScreen } from '../components/LoaderScreen' import { classNames } from '../utils/ui-helpers' -import { createHash } from '../utils/string-helpers' +import { createHash, md5Hash } from '../utils/string-helpers' import { ExitButton } from '../components/ExitButton' import { TitleBar } from '../components/TitleBar' +import { localData } from '../utils/storage' export const AuthScreen = () => { const [loading, setLoading] = useState(false) @@ -33,8 +34,14 @@ export const AuthScreen = () => { if (error) return toast.error(error.message) - setLoading(false) - resetForm() + if (user) { + // If login success then store hashed passphrase in localStorage + const hashedPassphrase = await md5Hash(password) + await localData.set('passphrase', hashedPassphrase) + setLoading(false) + } + + return resetForm() } const handleRegister = async () => { @@ -45,7 +52,7 @@ export const AuthScreen = () => { if (error) return toast.error(error.message) toast.success('Check your email to verify your account!') setActionIsLogin(true) - resetForm() + return resetForm() } const handleSubmit = async (e: React.FormEvent) => { diff --git a/apps/desktop/src/screens/ErrorScreen.tsx b/apps/desktop/src/screens/ErrorScreen.tsx index 196109c..bc06082 100644 --- a/apps/desktop/src/screens/ErrorScreen.tsx +++ b/apps/desktop/src/screens/ErrorScreen.tsx @@ -1,14 +1,18 @@ import { ShieldExclamationIcon } from '@heroicons/react/24/outline' +import { ExitButton } from '../components/ExitButton' export const ErrorScreen = ({ message }: { message: string }) => { return ( -
-
-
- -

{message || 'Something wrong :-('}

+ <> + +
+
+
+ +

{message || 'Something wrong :-('}

+
-
+ ) } diff --git a/apps/desktop/src/screens/MainScreen.tsx b/apps/desktop/src/screens/MainScreen.tsx index ad291d2..6ccfef0 100644 --- a/apps/desktop/src/screens/MainScreen.tsx +++ b/apps/desktop/src/screens/MainScreen.tsx @@ -24,7 +24,6 @@ export const MainScreen = (): JSX.Element => { // Fetch decrypted vaults data. // TODO: Use LyraSearch for local search indexing. - // const { isLoading, error, data, isFetching, refetch }: any = useLoadCollection(filter) const { isLoading, error, data, refetch }: any = useGetCollections({ filter }) if (isLoading && !filter) return diff --git a/apps/desktop/src/utils/string-helpers.ts b/apps/desktop/src/utils/string-helpers.ts index 0499878..0b75a61 100644 --- a/apps/desktop/src/utils/string-helpers.ts +++ b/apps/desktop/src/utils/string-helpers.ts @@ -47,7 +47,7 @@ export const encryptStr = async (plainStr: string): Promise => { export const decryptStr = async (encryptedStr: string): Promise => { const passphrase = await localData.get('passphrase') - return invoke('decrypt_str', { encryptedStr, passphrase }) + return await invoke('decrypt_str', { encryptedStr, passphrase }) } export const md5Hash = async (str: string): Promise => { diff --git a/libs/otentik-db/src/create-local-snapshot.ts b/libs/otentik-db/src/create-local-snapshot.ts index efd1fb4..288c07e 100755 --- a/libs/otentik-db/src/create-local-snapshot.ts +++ b/libs/otentik-db/src/create-local-snapshot.ts @@ -4,7 +4,7 @@ async function createLocalSnapshot() { // eslint-disable-next-line const { execSync } = require('child_process') - console.log('========== Create Snapshot ==========') + console.info('========== Create Snapshot ==========') const now = new Date() const inquirer = await import('inquirer') diff --git a/libs/otentik-db/src/create-production-snapshot.ts b/libs/otentik-db/src/create-production-snapshot.ts index 080bf97..20e48bf 100755 --- a/libs/otentik-db/src/create-production-snapshot.ts +++ b/libs/otentik-db/src/create-production-snapshot.ts @@ -4,7 +4,7 @@ async function createProductionSnapshot() { // eslint-disable-next-line const { execSync } = require('child_process') - console.log('========== Create Snapshot ==========') + console.info('========== Create Snapshot ==========') const now = new Date() const inquirer = await import('inquirer') diff --git a/libs/otentik-db/src/restore-snapshot.ts b/libs/otentik-db/src/restore-snapshot.ts index b10ce91..3e8ef42 100755 --- a/libs/otentik-db/src/restore-snapshot.ts +++ b/libs/otentik-db/src/restore-snapshot.ts @@ -9,7 +9,7 @@ async function restoreSnapshotToLocalDb() { // eslint-disable-next-line const path = require('path') - console.log('======== Restore Snapshot =========') + console.info('======== Restore Snapshot =========') const snapshotsPath = path.join(__dirname, '../supabase/snapshots') const snapshots = readdirSync(snapshotsPath) @@ -20,11 +20,11 @@ async function restoreSnapshotToLocalDb() { message: 'select a snapshot to restore', name: 'snapshot', }) - console.log(snapshot) + console.info(snapshot) - console.log('clearing current data') + console.info('clearing current data') execSync('PGPASSWORD=postgres psql -U postgres -h 127.0.0.1 -p 54322 -f libs/otentik-db/supabase/clear-db.sql') - console.log(`Restoring snapshot ${snapshot}...`) + console.info(`Restoring snapshot ${snapshot}...`) execSync( `PGPASSWORD=postgres psql -U postgres -h 127.0.0.1 -p 54322 -f libs/otentik-db/supabase/snapshots/${snapshot}` ) From 0330a0ff066e83e1ecee23d8b7e851dab2e08414 Mon Sep 17 00:00:00 2001 From: Aris Ripandi Date: Tue, 30 Aug 2022 04:32:00 +0700 Subject: [PATCH 3/5] add countdown timer indicator --- apps/desktop/src/components/AppMenu.tsx | 41 +++++---------------- apps/desktop/src/components/ProgressBar.tsx | 2 +- apps/desktop/src/screens/AuthScreen.tsx | 2 +- apps/desktop/src/screens/MainScreen.tsx | 32 +++++++++++++++- 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/apps/desktop/src/components/AppMenu.tsx b/apps/desktop/src/components/AppMenu.tsx index 6c5394c..afd8c6b 100644 --- a/apps/desktop/src/components/AppMenu.tsx +++ b/apps/desktop/src/components/AppMenu.tsx @@ -1,18 +1,16 @@ import { Fragment } from 'react' import { appWindow } from '@tauri-apps/api/window' import { ask, open, save } from '@tauri-apps/api/dialog' -// import { checkUpdate } from '@tauri-apps/api/updater' import { Menu, Transition } from '@headlessui/react' import { LockClosedIcon, - CogIcon, + ArrowPathIcon, ArrowRightOnRectangleIcon, DocumentPlusIcon, XCircleIcon, - ArchiveBoxIcon, - ArrowDownOnSquareIcon, - ArrowPathIcon, + ArrowUturnUpIcon, + ArrowUturnDownIcon, } from '@heroicons/react/24/outline' import { Bars3Icon } from '@heroicons/react/24/solid' import { useHotkeys } from 'react-hotkeys-hook' @@ -22,6 +20,7 @@ import { classNames } from '../utils/ui-helpers' import { sbClient } from '../utils/supabase' import { MenuDivider } from './MenuDivider' import { exportCollections, importCollections } from '../utils/import-export' +import { toast } from 'react-hot-toast' const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)) @@ -38,7 +37,7 @@ export const AppMenu = () => { } const handleImport = async () => { - // Open a selection dialog for image files + // Open a selection dialog for backup file const selected = await open({ multiple: false, filters: [ @@ -53,6 +52,7 @@ export const AppMenu = () => { // user selected multiple files } else if (selected === null) { // user cancelled the selection + toast.error('Canceled!') } else { // user selected a single file await importCollections(selected) @@ -82,14 +82,6 @@ export const AppMenu = () => { } } - const handleUpdate = async () => { - try { - // TODO: enable auto update check - } catch (error) { - console.error(error) - } - } - const handleSignOut = () => { resetStates() sbClient.auth.signOut().catch(console.error) @@ -115,7 +107,7 @@ export const AppMenu = () => { leaveFrom="transform opacity-100 scale-100" leaveTo="transform opacity-0 scale-95" > - + {!locked && ( <> @@ -145,21 +137,6 @@ export const AppMenu = () => { onClick={() => setForceFetch(true)} > Sync Vault - - - )} - - - {({ active }: { active: boolean }) => ( - )} @@ -176,7 +153,7 @@ export const AppMenu = () => { onClick={handleImport} > Import - + )} @@ -191,7 +168,7 @@ export const AppMenu = () => { onClick={handleExport} > Export - + )} diff --git a/apps/desktop/src/components/ProgressBar.tsx b/apps/desktop/src/components/ProgressBar.tsx index 71fd7f1..2613119 100644 --- a/apps/desktop/src/components/ProgressBar.tsx +++ b/apps/desktop/src/components/ProgressBar.tsx @@ -12,7 +12,7 @@ export const ProgressBar: FC = ({ percentage }) => {
= 60 ? 'from-blue-500 to-red-500' : 'from-cyan-500 to-blue-500', + percentage < 40 ? 'from-red-900 to-red-400' : 'from-red-500 to-blue-500', 'h-1.5 bg-gradient-to-r' )} >
diff --git a/apps/desktop/src/screens/AuthScreen.tsx b/apps/desktop/src/screens/AuthScreen.tsx index 3be87ac..42f7704 100644 --- a/apps/desktop/src/screens/AuthScreen.tsx +++ b/apps/desktop/src/screens/AuthScreen.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' import { ArrowRightCircleIcon } from '@heroicons/react/24/solid' -import toast from 'react-hot-toast' +import { toast } from 'react-hot-toast' import { sbClient } from '../utils/supabase' import { LoaderScreen } from '../components/LoaderScreen' diff --git a/apps/desktop/src/screens/MainScreen.tsx b/apps/desktop/src/screens/MainScreen.tsx index 6ccfef0..2325523 100644 --- a/apps/desktop/src/screens/MainScreen.tsx +++ b/apps/desktop/src/screens/MainScreen.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useIsFetching } from '@tanstack/react-query' import { useStores } from '../stores/stores' @@ -22,10 +22,37 @@ export const MainScreen = (): JSX.Element => { const setForceFetch = useStores((state) => state.setForceFetch) const [filter, setFilter] = useState('') + // Progress bar timer countdown + const [startTimer, setStartTimer] = useState(false) + const [percentage, setPercentage] = useState(100) + const [seconds, setSeconds] = useState(0) + // Fetch decrypted vaults data. // TODO: Use LyraSearch for local search indexing. const { isLoading, error, data, refetch }: any = useGetCollections({ filter }) + useEffect(() => { + if (isFetching) { + setStartTimer(true) + setPercentage(100) + setSeconds(30) + } + + const myInterval = setInterval(() => { + if (startTimer && seconds > 0) { + setPercentage(Math.trunc((300 * seconds) / 100)) + setSeconds(seconds - 1) + } + if (seconds === 0) { + setStartTimer(false) + setPercentage(100) + setSeconds(30) + } + }, 1000) + + return () => clearInterval(myInterval) + }, [startTimer, isFetching, seconds]) + if (isLoading && !filter) return if (!locked && error) return @@ -39,8 +66,9 @@ export const MainScreen = (): JSX.Element => { - +
+ {/*
{seconds === 0 ? null : seconds}
*/}
{isFetching && } From c350c8e2c4ecb7320eef1c9124a0b4c6f2bd974d Mon Sep 17 00:00:00 2001 From: Aris Ripandi Date: Tue, 30 Aug 2022 04:35:07 +0700 Subject: [PATCH 4/5] version bump to 0.4.0 --- apps/desktop/src-tauri/Cargo.toml | 2 +- apps/desktop/src-tauri/src/menu.rs | 2 +- apps/desktop/src-tauri/tauri.conf.json | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 76a88f5..547db2e 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "otentik-authenticator" -version = "0.3.0" +version = "0.4.0" description = "Open Source two factor authenticator" authors = ["Aris Ripandi "] license = "Apache-2.0" diff --git a/apps/desktop/src-tauri/src/menu.rs b/apps/desktop/src-tauri/src/menu.rs index 6bd1b54..8d25f62 100644 --- a/apps/desktop/src-tauri/src/menu.rs +++ b/apps/desktop/src-tauri/src/menu.rs @@ -9,7 +9,7 @@ pub(crate) fn menu() -> Menu { // App Menu (macOS) // --------------------------------------------------------------------------------------------- let about_menu = AboutMetadata::new() - .version(String::from("0.3.0")) + .version(String::from("0.4.0")) .authors(vec![String::from("Aris Ripandi")]) .comments(String::from("Open Source two factor authenticator")) .copyright(String::from("Apache-2.0 License")) diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index d10852d..30bf586 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Authenticator", - "version": "0.3.0" + "version": "0.4.0" }, "tauri": { "allowlist": { diff --git a/package.json b/package.json index 6db1120..7c7b4d0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "otentik", - "version": "0.3.0", + "version": "0.4.0", "license": "Apache-2.0", "private": true, "scripts": { From 95bee6567207cefa7711a0455e0e3a1e05c02a7a Mon Sep 17 00:00:00 2001 From: Aris Ripandi Date: Tue, 30 Aug 2022 04:41:26 +0700 Subject: [PATCH 5/5] version bump to 0.4.0 --- apps/desktop/src-tauri/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/src-tauri/Cargo.lock b/apps/desktop/src-tauri/Cargo.lock index e78c57f..8b4df08 100644 --- a/apps/desktop/src-tauri/Cargo.lock +++ b/apps/desktop/src-tauri/Cargo.lock @@ -2181,7 +2181,7 @@ dependencies = [ [[package]] name = "otentik-authenticator" -version = "0.3.0" +version = "0.4.0" dependencies = [ "bcrypt", "binascii",