mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-30 19:54:16 -04:00
wip: Replace the secure store
This commit is contained in:
parent
fee59833f2
commit
1237a9157c
@ -40,6 +40,7 @@
|
|||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-i18next": "^12.2.0",
|
"react-i18next": "^12.2.0",
|
||||||
"react-native": "0.71.8",
|
"react-native": "0.71.8",
|
||||||
|
"react-native-mmkv": "^2.10.1",
|
||||||
"react-native-reanimated": "~2.14.4",
|
"react-native-reanimated": "~2.14.4",
|
||||||
"react-native-safe-area-context": "4.5.0",
|
"react-native-safe-area-context": "4.5.0",
|
||||||
"react-native-screens": "~3.20.0",
|
"react-native-screens": "~3.20.0",
|
||||||
|
@ -24,7 +24,7 @@ import { Hydrate, QueryClientProvider } from "@tanstack/react-query";
|
|||||||
import { HiddenIfNoJs, SkeletonCss, ThemeSelector } from "@kyoo/primitives";
|
import { HiddenIfNoJs, SkeletonCss, ThemeSelector } from "@kyoo/primitives";
|
||||||
import { WebTooltip } from "@kyoo/primitives/src/tooltip.web";
|
import { WebTooltip } from "@kyoo/primitives/src/tooltip.web";
|
||||||
import { createQueryClient, fetchQuery, getTokenWJ, QueryIdentifier, QueryPage } from "@kyoo/models";
|
import { createQueryClient, fetchQuery, getTokenWJ, QueryIdentifier, QueryPage } from "@kyoo/models";
|
||||||
import { setSecureItemSync } from "@kyoo/models/src/secure-store.web";
|
import { setSecureItem } from "@kyoo/models/src/secure-store.web";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import NextApp, { AppContext, type AppProps } from "next/app";
|
import NextApp, { AppContext, type AppProps } from "next/app";
|
||||||
import { Poppins } from "next/font/google";
|
import { Poppins } from "next/font/google";
|
||||||
@ -101,7 +101,7 @@ const App = ({ Component, pageProps }: AppProps) => {
|
|||||||
|
|
||||||
// Set the auth from the server (if the token was refreshed during SSR).
|
// Set the auth from the server (if the token was refreshed during SSR).
|
||||||
if (typeof window !== "undefined" && token)
|
if (typeof window !== "undefined" && token)
|
||||||
setSecureItemSync("auth", JSON.stringify(token));
|
setSecureItem("auth", JSON.stringify(token));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<YoshikiDebug>
|
<YoshikiDebug>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"packageManager": "yarn@3.2.4",
|
"packageManager": "yarn@3.2.4",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.0.28",
|
"@types/react": "^18.0.28",
|
||||||
"expo-secure-store": "^12.1.1",
|
"react-native-mmkv": "^2.10.1",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -42,33 +42,31 @@ type Result<A, B> =
|
|||||||
export type Account = Token & { apiUrl: string; username: string };
|
export type Account = Token & { apiUrl: string; username: string };
|
||||||
|
|
||||||
export const useAccounts = () => {
|
export const useAccounts = () => {
|
||||||
const [accounts, setAccounts] = useState<Account[]>([]);
|
const [accounts] = useState<Account[]>(JSON.parse(getSecureItem("accounts") ?? "[]"));
|
||||||
const [selected, setSelected] = useState(0);
|
const [selected, setSelected] = useState<number>(parseInt(getSecureItem("selected") ?? "0"));
|
||||||
|
|
||||||
useEffect(() => {
|
return {
|
||||||
async function run() {
|
accounts,
|
||||||
setAccounts(JSON.parse(await getSecureItem("accounts") ?? "[]"));
|
selected,
|
||||||
}
|
setSelected: (selected: number) => {
|
||||||
|
setSelected(selected);
|
||||||
|
setSecureItem("selected", selected.toString());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
run();
|
const addAccount = (token: Token, apiUrl: string, username: string | null) => {
|
||||||
}, []);
|
const accounts: Account[] = JSON.parse(getSecureItem("accounts") ?? "[]");
|
||||||
return {accounts, selected, setSelected};
|
const accIdx = accounts.findIndex((x) => x.refresh_token === token.refresh_token);
|
||||||
}
|
if (accIdx === -1) accounts.push({ ...token, username: username!, apiUrl });
|
||||||
|
else accounts[accIdx] = { ...accounts[accIdx], ...token };
|
||||||
const addAccount = async (token: Token, apiUrl: string, username: string | null): Promise<void> => {
|
setSecureItem("accounts", JSON.stringify(accounts));
|
||||||
const accounts: Account[] = JSON.parse(await getSecureItem("accounts") ?? "[]");
|
};
|
||||||
const accIdx = accounts.findIndex(x => x.refresh_token === token.refresh_token);
|
|
||||||
if (accIdx === -1)
|
|
||||||
accounts.push({...token, username, apiUrl});
|
|
||||||
else
|
|
||||||
accounts[accIdx] = {...accounts[accIdx], ...token};
|
|
||||||
await setSecureItem("accounts", JSON.stringify(accounts));
|
|
||||||
}
|
|
||||||
|
|
||||||
export const loginFunc = async (
|
export const loginFunc = async (
|
||||||
action: "register" | "login" | "refresh",
|
action: "register" | "login" | "refresh",
|
||||||
body: { username: string, password: string, email?: string } | string,
|
body: { username: string; password: string; email?: string } | string,
|
||||||
apiUrl?: string
|
apiUrl?: string,
|
||||||
): Promise<Result<Token, string>> => {
|
): Promise<Result<Token, string>> => {
|
||||||
try {
|
try {
|
||||||
const token = await queryFn(
|
const token = await queryFn(
|
||||||
@ -107,23 +105,23 @@ export const getTokenWJ = async (cookies?: string): Promise<[string, Token] | [n
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getToken = async (cookies?: string): Promise<string | null> =>
|
export const getToken = async (cookies?: string): Promise<string | null> =>
|
||||||
(await getTokenWJ(cookies))[0]
|
(await getTokenWJ(cookies))[0];
|
||||||
|
|
||||||
export const logout = async () =>{
|
export const logout = async () => {
|
||||||
if (Platform.OS !== "web") {
|
if (Platform.OS !== "web") {
|
||||||
const tokenStr = await getSecureItem("auth");
|
const tokenStr = await getSecureItem("auth");
|
||||||
if (!tokenStr) return;
|
if (!tokenStr) return;
|
||||||
const token = TokenP.parse(JSON.parse(tokenStr));
|
const token = TokenP.parse(JSON.parse(tokenStr));
|
||||||
|
|
||||||
let accounts: Account[] = JSON.parse(await getSecureItem("accounts") ?? "[]");
|
let accounts: Account[] = JSON.parse((await getSecureItem("accounts")) ?? "[]");
|
||||||
accounts = accounts.filter(x => x.refresh_token !== token.refresh_token);
|
accounts = accounts.filter((x) => x.refresh_token !== token.refresh_token);
|
||||||
await setSecureItem("accounts", JSON.stringify(accounts));
|
await setSecureItem("accounts", JSON.stringify(accounts));
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteSecureItem("auth")
|
await deleteSecureItem("auth");
|
||||||
}
|
};
|
||||||
|
|
||||||
export const deleteAccount = async () => {
|
export const deleteAccount = async () => {
|
||||||
await queryFn({ path: ["auth", "me"], method: "DELETE"});
|
await queryFn({ path: ["auth", "me"], method: "DELETE" });
|
||||||
await logout();
|
await logout();
|
||||||
}
|
};
|
||||||
|
@ -18,8 +18,19 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export {
|
import { MMKV } from 'react-native-mmkv'
|
||||||
setItemAsync as setSecureItem,
|
|
||||||
deleteItemAsync as deleteSecureItem,
|
const storage = new MMKV();
|
||||||
getItemAsync as getSecureItem,
|
|
||||||
} from "expo-secure-store";
|
export const setSecureItem = (key: string, value: string | null) => {
|
||||||
|
if (value === null)
|
||||||
|
storage.delete(key);
|
||||||
|
else
|
||||||
|
storage.set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteSecureItem = (key: string) => setSecureItem(key, null);
|
||||||
|
|
||||||
|
export const getSecureItem = (key: string, _cookies?: string): string | null => {
|
||||||
|
return storage.getString(key) || null;
|
||||||
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const setSecureItemSync = (key: string, value: string | null) => {
|
export const setSecureItem = (key: string, value: string | null) => {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
// A year
|
// A year
|
||||||
d.setTime(d.getTime() + 365 * 24 * 60 * 60 * 1000);
|
d.setTime(d.getTime() + 365 * 24 * 60 * 60 * 1000);
|
||||||
@ -27,12 +27,9 @@ export const setSecureItemSync = (key: string, value: string | null) => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setSecureItem = async (key: string, value: string | null): Promise<null> =>
|
export const deleteSecureItem = (key: string) => setSecureItem(key, null);
|
||||||
setSecureItemSync(key, value);
|
|
||||||
|
|
||||||
export const deleteSecureItem = async (key: string) => setSecureItem(key, null);
|
export const getSecureItem = (key: string, cookies?: string): string | null => {
|
||||||
|
|
||||||
export const getSecureItem = async (key: string, cookies?: string): Promise<string | null> => {
|
|
||||||
// Don't try to use document's cookies on SSR.
|
// Don't try to use document's cookies on SSR.
|
||||||
if (!cookies && typeof window === "undefined") return null;
|
if (!cookies && typeof window === "undefined") return null;
|
||||||
const name = key + "=";
|
const name = key + "=";
|
||||||
|
@ -2263,7 +2263,7 @@ __metadata:
|
|||||||
resolution: "@kyoo/models@workspace:packages/models"
|
resolution: "@kyoo/models@workspace:packages/models"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react": ^18.0.28
|
"@types/react": ^18.0.28
|
||||||
expo-secure-store: ^12.1.1
|
react-native-mmkv: ^2.10.1
|
||||||
typescript: ^4.9.5
|
typescript: ^4.9.5
|
||||||
zod: ^3.21.4
|
zod: ^3.21.4
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -6907,7 +6907,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"expo-secure-store@npm:^12.1.1, expo-secure-store@npm:~12.1.1":
|
"expo-secure-store@npm:~12.1.1":
|
||||||
version: 12.1.1
|
version: 12.1.1
|
||||||
resolution: "expo-secure-store@npm:12.1.1"
|
resolution: "expo-secure-store@npm:12.1.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -10339,6 +10339,7 @@ __metadata:
|
|||||||
react-dom: 18.2.0
|
react-dom: 18.2.0
|
||||||
react-i18next: ^12.2.0
|
react-i18next: ^12.2.0
|
||||||
react-native: 0.71.8
|
react-native: 0.71.8
|
||||||
|
react-native-mmkv: ^2.10.1
|
||||||
react-native-reanimated: ~2.14.4
|
react-native-reanimated: ~2.14.4
|
||||||
react-native-safe-area-context: 4.5.0
|
react-native-safe-area-context: 4.5.0
|
||||||
react-native-screens: ~3.20.0
|
react-native-screens: ~3.20.0
|
||||||
@ -11678,6 +11679,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"react-native-mmkv@npm:^2.10.1":
|
||||||
|
version: 2.10.1
|
||||||
|
resolution: "react-native-mmkv@npm:2.10.1"
|
||||||
|
peerDependencies:
|
||||||
|
react: "*"
|
||||||
|
react-native: ">=0.71.0"
|
||||||
|
checksum: 2db42a667acd104047ddf307e852ffd9d9c6302454364fcc4cd35d8510d6f500bcd3562e14d95ae7fd520eac1cd3cc8a239c539a7339b70a4e6fd2d3f70daee7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-native-reanimated@npm:2.14.4, react-native-reanimated@npm:~2.14.4":
|
"react-native-reanimated@npm:2.14.4, react-native-reanimated@npm:~2.14.4":
|
||||||
version: 2.14.4
|
version: 2.14.4
|
||||||
resolution: "react-native-reanimated@npm:2.14.4"
|
resolution: "react-native-reanimated@npm:2.14.4"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user