-
-
Authenticated with GitHub
-
-
@Username
-
-
-
-
- Country: Germany
Wallet:
- Connect Now
-
+{#if user}
+
+
+

+
+
+
Authenticated with GitHub
+
+
@{user.login}
+
+
+
+
+ Country: {user?.country}
Wallet:
+ {#if user.wallet}
+ {user.wallet}
+ {:else}
+ Connect Now
+ {/if}
+
+
-
-
+
+{/if}
diff --git a/modules/gui/src/libs/api/mock.ts b/modules/gui/src/libs/api/mock.ts
index d4172f7..45beba2 100644
--- a/modules/gui/src/libs/api/mock.ts
+++ b/modules/gui/src/libs/api/mock.ts
@@ -11,6 +11,8 @@ import { PackageStates } from '../types';
import { loremIpsum } from 'lorem-ipsum';
import _ from 'lodash';
+export const apiBaseUrl = 'https://api.tea.xyz/v1';
+
const packages: Package[] = [
{
slug: 'mesonbuild_com',
@@ -323,6 +325,24 @@ export async function getCategorizedPackages(): Promise
{
];
}
+export async function getDeviceAuth(deviceId: string): Promise {
+ // const data = await get(`/auth/device/${deviceId}`);
+ return {
+ status: 'SUCCESS',
+ user: {
+ developer_id: 'xxx',
+ name: 'Neil paul Molina',
+ login: 'getneil',
+ avatar_url: 'https://avatars.githubusercontent.com/u/7913978?v=4',
+ created_at: 'xxx',
+ updated_at: 'xxx',
+ country: 'germany',
+ wallet: 'wallet'
+ },
+ key: 'xxx'
+ };
+}
+
export async function getPackageBottles(name: string): Promise {
return [
{ name, platform: 'darwin', arch: 'aarch64', version: '3.39.4' },
@@ -335,3 +355,7 @@ export async function getPackageBottles(name: string): Promise {
{ name, platform: 'linux', arch: 'x86-64', version: '3.40.0' }
];
}
+
+export async function registerDevice(): Promise {
+ return 'uuid1234';
+}
diff --git a/modules/gui/src/libs/api/tauri.ts b/modules/gui/src/libs/api/tauri.ts
index b034e55..4e38a07 100644
--- a/modules/gui/src/libs/api/tauri.ts
+++ b/modules/gui/src/libs/api/tauri.ts
@@ -14,20 +14,25 @@ import { getClient } from '@tauri-apps/api/http';
// import { invoke } from '@tauri-apps/api';
import { Command } from '@tauri-apps/api/shell';
import { readDir, BaseDirectory } from '@tauri-apps/api/fs';
-import type { Package, Review, AirtablePost, Bottle } from '@tea/ui/types';
-import type { GUIPackage, Course, Category } from '../types';
+
+import type { Package, Review, AirtablePost, Developer, Bottle } from '@tea/ui/types';
+import type { GUIPackage, Course, Category, AuthStatus } from '../types';
+
import * as mock from './mock';
import { PackageStates } from '../types';
-const base = 'https://api.tea.xyz/v1';
+export const apiBaseUrl = 'https://api.tea.xyz/v1';
+// const apiBaseUrl = 'http://localhost:3000/v1';
async function get(path: string, query?: { [key: string]: string }) {
+ console.log('path', path);
const client = await getClient();
- const uri = join(base, path);
+ const uri = join(apiBaseUrl, path);
+ console.log('uri:', uri);
const { data } = await client.get(uri.toString(), {
headers: {
- Authorization: 'public', // TODO: figure out why req w/o Authorization does not work
- 'cache-control': 'no-cache'
+ Authorization: 'public' // TODO: figure out why req w/o Authorization does not work
+ // 'cache-control': 'no-cache'
},
query: query || {}
});
@@ -164,6 +169,17 @@ export async function getCategorizedPackages(): Promise {
return categories;
}
+type DeviceAuth = {
+ status: AuthStatus;
+ user: Developer;
+ key: string;
+};
+
+export async function getDeviceAuth(deviceId: string): Promise {
+ const data = await get(`/auth/device/${deviceId}`);
+ return data;
+}
+
export async function getPackageBottles(packageName: string): Promise {
console.log('getting bottles for ', packageName);
const client = await getClient();
@@ -172,3 +188,8 @@ export async function getPackageBottles(packageName: string): Promise
console.log('got bottles', data);
return data;
}
+
+export async function registerDevice(): Promise {
+ const { deviceId } = await get<{ deviceId: string }>('/auth/registerDevice');
+ return deviceId;
+}
diff --git a/modules/gui/src/libs/stores.ts b/modules/gui/src/libs/stores.ts
index 316139a..2fcb107 100644
--- a/modules/gui/src/libs/stores.ts
+++ b/modules/gui/src/libs/stores.ts
@@ -5,6 +5,7 @@ import type { Package, Review, AirtablePost } from '@tea/ui/types';
import type { GUIPackage } from '$libs/types';
import { getPackages, getFeaturedPackages, getPackageReviews, getAllPosts } from '@api';
+import initAuthStore from './stores/auth';
export const backLink = writable('/');
@@ -169,3 +170,5 @@ function initSearchStore() {
}
export const searchStore = initSearchStore();
+
+export const authStore = initAuthStore();
diff --git a/modules/gui/src/libs/stores/auth.ts b/modules/gui/src/libs/stores/auth.ts
new file mode 100644
index 0000000..739a1c9
--- /dev/null
+++ b/modules/gui/src/libs/stores/auth.ts
@@ -0,0 +1,115 @@
+import { writable } from 'svelte/store';
+import { BaseDirectory, createDir, readTextFile, writeTextFile } from '@tauri-apps/api/fs';
+import { join } from '@tauri-apps/api/path';
+import { getDeviceAuth, registerDevice } from '@api';
+import type { Developer } from '@tea/ui/types';
+
+const basePath = '.tea/tea.xyz/gui';
+interface Session {
+ device_id?: string;
+ key?: string;
+ user?: Developer;
+}
+
+export default function initAuthStore() {
+ const session = writable({});
+ let pollLoop = 0;
+
+ const deviceIdStore = writable('');
+ let deviceId = '';
+
+ initSession().then((sess) => {
+ if (sess) {
+ session.set(sess);
+ deviceIdStore.set(sess.device_id!);
+ deviceId = sess.device_id!;
+ }
+ });
+
+ let timer: NodeJS.Timer | null;
+
+ async function updateSession(data: Session) {
+ const localSession = {
+ device_id: deviceId,
+ key: data.key,
+ user: data.user
+ };
+ saveLocallySessionData(localSession);
+ session.set(localSession);
+ }
+
+ async function pollSession() {
+ if (!timer) {
+ timer = setInterval(async () => {
+ pollLoop++;
+ try {
+ const data = await getDeviceAuth(deviceId);
+ console.log('dd', deviceId, data);
+ if (data.status === 'SUCCESS') {
+ updateSession({
+ key: data.key,
+ user: data.user
+ });
+ timer && clearInterval(timer);
+ timer = null;
+ }
+ } catch (error) {
+ console.error(error);
+ }
+
+ if (pollLoop > 20 && timer) {
+ clearInterval(timer);
+ pollLoop = 0;
+ timer = null;
+ }
+ }, 2000);
+ }
+ }
+
+ return {
+ deviceId,
+ deviceIdStore,
+ subscribe: (cb: (u: Developer) => void) => {
+ return session.subscribe((v) => v?.user && cb(v.user));
+ },
+ pollSession
+ };
+}
+
+const initSession = async (): Promise => {
+ await createDir(basePath, {
+ dir: BaseDirectory.Home,
+ recursive: true
+ });
+ const session = await getLocalSessionData();
+ return session;
+};
+
+const getLocalSessionData = async (): Promise => {
+ const sessionFilePath = await join(basePath, 'tmp.dat');
+ let data: Session;
+ try {
+ const encryptedData = await readTextFile(sessionFilePath, {
+ dir: BaseDirectory.Home
+ });
+ // TODO: decrypt then return
+ data = JSON.parse(encryptedData || '{}');
+ } catch (error) {
+ console.error(error);
+ const deviceId = await registerDevice();
+ data = {
+ device_id: deviceId
+ };
+ await saveLocallySessionData(data);
+ }
+
+ return data;
+};
+
+const saveLocallySessionData = async (data: Session) => {
+ const sessionFilePath = await join(basePath, 'tmp.dat');
+ // TODO: encrypt first
+ await writeTextFile(sessionFilePath, JSON.stringify(data), {
+ dir: BaseDirectory.Home
+ });
+};
diff --git a/modules/gui/src/libs/types.ts b/modules/gui/src/libs/types.ts
index b4617f4..dd9f8be 100644
--- a/modules/gui/src/libs/types.ts
+++ b/modules/gui/src/libs/types.ts
@@ -29,3 +29,10 @@ export type Category = {
cta_label: string;
packages: GUIPackage[];
};
+
+export enum AuthStatus {
+ UNKNOWN = 'UNKNOWN',
+ PENDING = 'PENDING',
+ SUCCESS = 'SUCCESS',
+ FAILED = 'FAILED'
+}
diff --git a/modules/gui/src/routes/+page.svelte b/modules/gui/src/routes/+page.svelte
index cb33f10..78f5400 100644
--- a/modules/gui/src/routes/+page.svelte
+++ b/modules/gui/src/routes/+page.svelte
@@ -9,6 +9,7 @@
import News from '$components/News/News.svelte';
import CategorizedPackages from '$components/CategorizedPackages/CategorizedPackages.svelte';
backLink.set('');
+ console.log('test', window.location);
diff --git a/modules/gui/src/routes/profile/+page.svelte b/modules/gui/src/routes/profile/+page.svelte
index 21855de..149a3ec 100644
--- a/modules/gui/src/routes/profile/+page.svelte
+++ b/modules/gui/src/routes/profile/+page.svelte
@@ -11,7 +11,6 @@
PROFILE
-
diff --git a/modules/gui/static/images/github.png b/modules/gui/static/images/github.png
new file mode 100644
index 0000000..3a1bfa4
Binary files /dev/null and b/modules/gui/static/images/github.png differ
diff --git a/modules/ui/src/types.ts b/modules/ui/src/types.ts
index 606cbf2..afc7524 100644
--- a/modules/ui/src/types.ts
+++ b/modules/ui/src/types.ts
@@ -35,6 +35,15 @@ export type AirtablePost = {
tags: string[];
};
+export type Developer = {
+ developer_id: string;
+ avatar_url?: string;
+ name: string;
+ login: string;
+ country?: string;
+ wallet?: string;
+};
+
export type Bottle = {
name: string;
platform: string;