wip: multi account

This commit is contained in:
Ren Amamiya 2023-09-28 13:58:50 +07:00
parent 0e6fc65b08
commit 4f4e2f5ccd
11 changed files with 59 additions and 30 deletions

BIN
public/wallpapers/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 MiB

View File

@ -24,7 +24,7 @@ export default function App() {
const accountLoader = async () => {
try {
const account = await db.checkAccount();
const totalAccount = await db.checkAccount();
const stronghold = sessionStorage.getItem('stronghold');
const privkey = JSON.parse(stronghold).state.privkey || null;
@ -32,7 +32,7 @@ export default function App() {
const onboarding = localStorage.getItem('onboarding');
const step = JSON.parse(onboarding).state.step || null;
if (!account) {
if (totalAccount === 0) {
return redirect('/auth/welcome');
} else {
if (step) {
@ -251,6 +251,13 @@ export default function App() {
return { Component: UnlockScreen };
},
},
{
path: 'lock',
async lazy() {
const { LockScreen } = await import('@app/auth/lock');
return { Component: LockScreen };
},
},
{
path: 'migrate',
async lazy() {

View File

@ -66,7 +66,7 @@ export function CreateStep2Screen() {
if (!db.secureDB) db.secureDB = stronghold;
// save privkey to secure storage
await db.secureSave(pubkey, privkey);
await db.secureSave(pubkey, privkey, pubkey);
// redirect to next step
navigate('/auth/create/step-3', { replace: true });

View File

@ -66,7 +66,7 @@ export function ImportStep2Screen() {
if (!db.secureDB) db.secureDB = stronghold;
// save privkey to secure storage
await db.secureSave(pubkey, privkey);
await db.secureSave(pubkey, privkey, pubkey);
// redirect to next step
navigate('/auth/import/step-3', { replace: true });

10
src/app/auth/lock.tsx Normal file
View File

@ -0,0 +1,10 @@
export function LockScreen() {
return (
<div
className="h-full w-full bg-cover bg-center"
style={{ backgroundImage: 'url(/wallpapers/1.png)' }}
>
<p>TODO</p>
</div>
);
}

View File

@ -33,6 +33,7 @@ export function UnlockScreen() {
const navigate = useNavigate();
const setPrivkey = useStronghold((state) => state.setPrivkey);
const setWalletConnectURL = useStronghold((state) => state.setWalletConnectURL);
const resetStronghold = useStronghold((state) => state.reset);
const [showPassword, setShowPassword] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
@ -73,6 +74,8 @@ export function UnlockScreen() {
const logout = async () => {
// remove account
db.accountLogout();
// reset stronghold
resetStronghold();
// redirect to welcome screen
navigate('/auth/welcome');
};
@ -146,7 +149,7 @@ export function UnlockScreen() {
to="/auth/reset"
className="inline-flex h-10 w-full items-center justify-center rounded-lg text-center text-sm font-medium text-white/70 hover:bg-white/20"
>
Reset password if you still have private key
Reset password if you still have a private key
</Link>
<button
type="button"

View File

@ -68,7 +68,7 @@ export function SplashScreen() {
</h3>
{ndk ? (
<p className="text-sm text-white/50">
Ensure all your data is sync across all Nostr clients, it may take a few
Ensure all your data is sync across all Nostr clients. It may take a few
seconds, please don&apos;t close app.
</p>
) : null}

View File

@ -35,7 +35,6 @@ export class LumeStorage {
const client = await this.getSecureClient(clientKey);
const store = client.getStore();
console.log('insert key: ', key);
await store.insert(key, Array.from(new TextEncoder().encode(value)));
await this.secureDB.save();
@ -46,7 +45,6 @@ export class LumeStorage {
const client = await this.getSecureClient(clientKey);
const store = client.getStore();
console.log('get key: ', key);
const value = await store.get(key);
if (!value) return null;
@ -60,10 +58,10 @@ export class LumeStorage {
}
public async checkAccount() {
const result: Array<Account> = await this.db.select(
'SELECT * FROM accounts WHERE is_active = 1;'
const result: Array<{ total: string }> = await this.db.select(
'SELECT COUNT(*) AS "total" FROM accounts;'
);
return result.length > 0;
return parseInt(result[0].total);
}
public async getActiveAccount() {
@ -92,16 +90,24 @@ export class LumeStorage {
}
public async createAccount(npub: string, pubkey: string) {
const res = await this.db.execute(
'INSERT OR IGNORE INTO accounts (npub, pubkey, privkey, is_active) VALUES ($1, $2, $3, $4);',
[npub, pubkey, 'privkey is stored in secure storage', 1]
const existAccounts: Array<Account> = await this.db.select(
'SELECT * FROM accounts WHERE pubkey = $1 ORDER BY id DESC LIMIT 1;',
[pubkey]
);
if (res) {
const account = await this.getActiveAccount();
return account;
if (existAccounts.length > 0) {
await this.db.execute("UPDATE accounts SET is_active = '1' WHERE pubkey = $1;", [
pubkey,
]);
} else {
console.error('create account failed');
await this.db.execute(
'INSERT OR IGNORE INTO accounts (npub, pubkey, privkey, is_active) VALUES ($1, $2, $3, $4);',
[npub, pubkey, 'privkey is stored in secure storage', 1]
);
}
const account = await this.getActiveAccount();
return account;
}
public async updateAccount(column: string, value: string | string[]) {
@ -191,7 +197,8 @@ export class LumeStorage {
public async countTotalEvents() {
const result: Array<{ total: string }> = await this.db.select(
'SELECT COUNT(*) AS "total" FROM events;'
'SELECT COUNT(*) AS "total" FROM events WHERE account_id = $1;',
[this.account.id]
);
return parseInt(result[0].total);
}
@ -206,8 +213,8 @@ export class LumeStorage {
};
const query: DBEvent[] = await this.db.select(
'SELECT * FROM events GROUP BY root_id ORDER BY created_at DESC LIMIT $1 OFFSET $2;',
[limit, offset]
'SELECT * FROM events WHERE account_id = $1 GROUP BY root_id ORDER BY created_at DESC LIMIT $2 OFFSET $3;',
[this.account.id, limit, offset]
);
if (query && query.length > 0) {
@ -264,8 +271,8 @@ export class LumeStorage {
};
const query: DBEvent[] = await this.db.select(
`SELECT * FROM events WHERE kinds IN (${authorsArr}) ORDER BY created_at DESC LIMIT $1 OFFSET $2;`,
[limit, offset]
`SELECT * FROM events WHERE kinds IN (${authorsArr}) AND account_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3;`,
[this.account.id, limit, offset]
);
if (query && query.length > 0) {
@ -284,7 +291,8 @@ export class LumeStorage {
public async isEventsEmpty() {
const results: DBEvent[] = await this.db.select(
'SELECT * FROM events ORDER BY id DESC LIMIT 1;'
'SELECT * FROM events WHERE account_id = $1 ORDER BY id DESC LIMIT 1;',
[this.account.id]
);
return results.length < 1;
@ -351,9 +359,6 @@ export class LumeStorage {
}
public async accountLogout() {
// delete all events
await this.db.execute('DELETE FROM events WHERE account_id = $1;', [this.account.id]);
// update current account status
await this.db.execute("UPDATE accounts SET is_active = '0' WHERE id = $1;", [
this.account.id,

View File

@ -11,13 +11,13 @@ export function Logout() {
const { db } = useStorage();
const navigate = useNavigate();
const clearPrivkey = useStronghold((state) => state.clearPrivkey);
const resetStronghold = useStronghold((state) => state.reset);
const logout = async () => {
// remove account
db.accountLogout();
// clear privkey in session storage
clearPrivkey();
resetStronghold();
// redirect to welcome screen
navigate('/auth/welcome');
};

View File

@ -56,7 +56,7 @@ export function EventLoader({ firstTime }: { firstTime: boolean }) {
) : (
<div className="text-center">
<h3 className="font-semibold leading-tight">
Downloading all events from your last login...
Downloading all events while you&apos;re away...
</h3>
</div>
)}

View File

@ -9,6 +9,7 @@ interface StrongholdState {
setWalletConnectURL: (uri: string) => void;
clearPrivkey: () => void;
setIsFetched: () => void;
reset: () => void;
}
export const useStronghold = create<StrongholdState>()(
@ -29,6 +30,9 @@ export const useStronghold = create<StrongholdState>()(
setIsFetched: () => {
set({ isFetched: true });
},
reset: () => {
set({ privkey: null, walletConnectURL: null, isFetched: false });
},
}),
{
name: 'stronghold',