mirror of
https://github.com/ivabus/gui
synced 2025-06-07 15:50:27 +03:00
Merge pull request #131 from teaxyz/secure-authorization
#129 secure auth
This commit is contained in:
commit
c93ce6ec0b
6 changed files with 477 additions and 305 deletions
|
@ -42,6 +42,8 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
|
"@types/bcryptjs": "^2.4.2",
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"fuse.js": "^6.6.2",
|
"fuse.js": "^6.6.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
|
|
@ -20,20 +20,41 @@ import type { GUIPackage, Course, Category, AuthStatus } from '../types';
|
||||||
|
|
||||||
import * as mock from './mock';
|
import * as mock from './mock';
|
||||||
import { PackageStates } from '../types';
|
import { PackageStates } from '../types';
|
||||||
|
import { getSession } from '$libs/stores/auth';
|
||||||
|
import type { Session } from '$libs/stores/auth';
|
||||||
|
import bcrypt from 'bcryptjs';
|
||||||
|
|
||||||
export const apiBaseUrl = 'https://api.tea.xyz/v1';
|
export const apiBaseUrl = 'https://api.tea.xyz/v1';
|
||||||
// const apiBaseUrl = 'http://localhost:3000/v1';
|
// export const apiBaseUrl = 'http://localhost:3000/v1';
|
||||||
|
|
||||||
|
async function getHeaders(path: string, session: Session) {
|
||||||
|
const unixMs = new Date().getTime();
|
||||||
|
const unixHexSecs = Math.round(unixMs / 1000).toString(16); // hex
|
||||||
|
const deviceId = session.device_id?.split('-')[0];
|
||||||
|
const preHash = [unixHexSecs, session.key, deviceId, path].join('');
|
||||||
|
|
||||||
|
const Authorization = bcrypt.hashSync(preHash, 10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
Authorization,
|
||||||
|
['tea-ts']: unixMs.toString(),
|
||||||
|
['tea-uid']: session.user?.developer_id,
|
||||||
|
['tea-gui_id']: session.device_id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function get<T>(path: string, query?: { [key: string]: string }) {
|
async function get<T>(path: string, query?: { [key: string]: string }) {
|
||||||
console.log('path', path);
|
const [session, client] = await Promise.all([getSession(), getClient()]);
|
||||||
const client = await getClient();
|
|
||||||
const uri = join(apiBaseUrl, path);
|
const uri = join(apiBaseUrl, path);
|
||||||
console.log('uri:', uri);
|
|
||||||
|
const headers =
|
||||||
|
session?.device_id && session?.user
|
||||||
|
? await getHeaders(`GET/${path}`, session)
|
||||||
|
: { Authorization: 'public ' };
|
||||||
|
|
||||||
const { data } = await client.get<T>(uri.toString(), {
|
const { data } = await client.get<T>(uri.toString(), {
|
||||||
headers: {
|
headers,
|
||||||
Authorization: 'public' // TODO: figure out why req w/o Authorization does not work
|
|
||||||
// 'cache-control': 'no-cache'
|
|
||||||
},
|
|
||||||
query: query || {}
|
query: query || {}
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
|
@ -79,6 +100,7 @@ export async function getPackageReviews(full_name: string): Promise<Review[]> {
|
||||||
const reviews: Review[] = await get<Review[]>(
|
const reviews: Review[] = await get<Review[]>(
|
||||||
`packages/${full_name.replaceAll('/', ':')}/reviews`
|
`packages/${full_name.replaceAll('/', ':')}/reviews`
|
||||||
);
|
);
|
||||||
|
|
||||||
return reviews;
|
return reviews;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ function initPackagesStore() {
|
||||||
export const packagesStore = initPackagesStore();
|
export const packagesStore = initPackagesStore();
|
||||||
|
|
||||||
export const initializeFeaturedPackages = async () => {
|
export const initializeFeaturedPackages = async () => {
|
||||||
console.log('initialzie featured packages');
|
console.log('intialize featured packages');
|
||||||
const packages = await getFeaturedPackages();
|
const packages = await getFeaturedPackages();
|
||||||
featuredPackages.set(packages);
|
featuredPackages.set(packages);
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,14 +5,25 @@ import { getDeviceAuth, registerDevice } from '@api';
|
||||||
import type { Developer } from '@tea/ui/types';
|
import type { Developer } from '@tea/ui/types';
|
||||||
|
|
||||||
const basePath = '.tea/tea.xyz/gui';
|
const basePath = '.tea/tea.xyz/gui';
|
||||||
interface Session {
|
export interface Session {
|
||||||
device_id?: string;
|
device_id?: string;
|
||||||
key?: string;
|
key?: string;
|
||||||
user?: Developer;
|
user?: Developer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export let session: Session | null = null;
|
||||||
|
export const getSession = async (): Promise<Session | null> => {
|
||||||
|
if (session && session?.user) return session;
|
||||||
|
const sessionFilePath = await join(basePath, 'tmp.dat');
|
||||||
|
const encryptedData = await readTextFile(sessionFilePath, {
|
||||||
|
dir: BaseDirectory.Home
|
||||||
|
});
|
||||||
|
session = JSON.parse(encryptedData || '{}') as Session;
|
||||||
|
return session;
|
||||||
|
};
|
||||||
|
|
||||||
export default function initAuthStore() {
|
export default function initAuthStore() {
|
||||||
const session = writable<Session>({});
|
const sessionStore = writable<Session>({});
|
||||||
let pollLoop = 0;
|
let pollLoop = 0;
|
||||||
|
|
||||||
const deviceIdStore = writable<string>('');
|
const deviceIdStore = writable<string>('');
|
||||||
|
@ -20,7 +31,8 @@ export default function initAuthStore() {
|
||||||
|
|
||||||
initSession().then((sess) => {
|
initSession().then((sess) => {
|
||||||
if (sess) {
|
if (sess) {
|
||||||
session.set(sess);
|
session = sess;
|
||||||
|
sessionStore.set(sess);
|
||||||
deviceIdStore.set(sess.device_id!);
|
deviceIdStore.set(sess.device_id!);
|
||||||
deviceId = sess.device_id!;
|
deviceId = sess.device_id!;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +47,7 @@ export default function initAuthStore() {
|
||||||
user: data.user
|
user: data.user
|
||||||
};
|
};
|
||||||
saveLocallySessionData(localSession);
|
saveLocallySessionData(localSession);
|
||||||
session.set(localSession);
|
sessionStore.set(localSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pollSession() {
|
async function pollSession() {
|
||||||
|
@ -70,7 +82,7 @@ export default function initAuthStore() {
|
||||||
deviceId,
|
deviceId,
|
||||||
deviceIdStore,
|
deviceIdStore,
|
||||||
subscribe: (cb: (u: Developer) => void) => {
|
subscribe: (cb: (u: Developer) => void) => {
|
||||||
return session.subscribe((v) => v?.user && cb(v.user));
|
return sessionStore.subscribe((v) => v?.user && cb(v.user));
|
||||||
},
|
},
|
||||||
pollSession
|
pollSession
|
||||||
};
|
};
|
||||||
|
@ -86,14 +98,12 @@ const initSession = async (): Promise<Session | void> => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLocalSessionData = async (): Promise<Session | void> => {
|
const getLocalSessionData = async (): Promise<Session | void> => {
|
||||||
const sessionFilePath = await join(basePath, 'tmp.dat');
|
|
||||||
let data: Session;
|
let data: Session;
|
||||||
try {
|
try {
|
||||||
const encryptedData = await readTextFile(sessionFilePath, {
|
const session = await getSession();
|
||||||
dir: BaseDirectory.Home
|
if (session) {
|
||||||
});
|
data = session;
|
||||||
// TODO: decrypt then return
|
}
|
||||||
data = JSON.parse(encryptedData || '{}');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
const deviceId = await registerDevice();
|
const deviceId = await registerDevice();
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
import News from '$components/News/News.svelte';
|
import News from '$components/News/News.svelte';
|
||||||
import CategorizedPackages from '$components/CategorizedPackages/CategorizedPackages.svelte';
|
import CategorizedPackages from '$components/CategorizedPackages/CategorizedPackages.svelte';
|
||||||
backLink.set('');
|
backLink.set('');
|
||||||
console.log('test', window.location);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
707
pnpm-lock.yaml
707
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue