* #328 improve auth initialization

* #328 sync logs to s3

---------

Co-authored-by: neil molina <neil@neils-MacBook-Pro.local>
This commit is contained in:
Neil 2023-03-23 16:42:56 +08:00 committed by GitHub
parent f5f87ebe4b
commit a47c1bf5c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 137 additions and 14 deletions

View file

@ -5,6 +5,7 @@ import { getTeaPath } from "./tea-dir";
import * as v1Client from "./v1-client";
import { app } from "electron";
import * as log from "electron-log";
import axios from "axios";
const sessionFilePath = path.join(getTeaPath(), "tea.xyz/gui/tmp.dat");
const sessionFolder = path.join(getTeaPath(), "tea.xyz/gui");
@ -16,27 +17,79 @@ export interface Session {
locale?: string;
}
let sessionMemory: Session = { device_id: "", locale: "en" };
const initialized: Promise<Session> = new Promise((resolve, reject) => {
try {
log.info("initializing GUI session folder");
createInitialSessionFile().then((newSession) => {
resolve(newSession);
});
} catch (error) {
log.error(error);
reject(error);
}
});
async function createInitialSessionFile(): Promise<Session> {
let session = {
...sessionMemory
};
try {
const locale = app.getLocale();
if (fs.existsSync(sessionFilePath)) {
log.info("session file exists!");
const sessionBuffer = await fs.readFileSync(sessionFilePath);
const session = JSON.parse(sessionBuffer.toString()) as Session;
session.locale = locale;
} else {
log.info("session file does not exists!");
await mkdirp(sessionFolder);
const req = await axios.get<{ deviceId: string }>(
"https://api.tea.xyz/v1/auth/registerDevice"
);
const data = { device_id: "", locale };
if (req && req.data.deviceId) {
data.device_id = req.data.deviceId;
log.info("got device_id", data);
await writeSessionData(data);
}
session = data;
}
} catch (error) {
log.error(error);
}
return session;
}
export async function readSessionData(): Promise<Session> {
const locale = app.getLocale();
log.info("read session data.");
const data = await initialized;
log.info("initialized session exists:", !!data);
if (sessionMemory) {
log.info("use session cache");
return sessionMemory;
}
try {
log.info("reading session data");
const locale = app.getLocale();
const sessionBuffer = await fs.readFileSync(sessionFilePath);
const session = JSON.parse(sessionBuffer.toString()) as Session;
session.locale = locale;
return session;
sessionMemory = session;
log.info("read session data");
} catch (error) {
log.error(error);
log.info("requesting device_id");
const req = await v1Client.get<{ deviceId: string }>("/auth/registerDevice");
const data = { device_id: req.deviceId, locale };
log.info("got device_id", data);
await writeSessionData(data);
return data;
}
return sessionMemory;
}
export async function writeSessionData(data: Session) {
try {
sessionMemory = {
...sessionMemory,
...data
};
log.info("creating:", sessionFolder);
await mkdirp(sessionFolder);
log.info("writing session data:", data); // rm this

View file

@ -1,13 +1,17 @@
import { ipcMain } from "electron";
import { ipcMain, app } from "electron";
import { createReadStream, statSync } from "fs";
import { getInstalledPackages } from "./tea-dir";
import { readSessionData, writeSessionData } from "./auth";
import type { Session, InstalledPackage } from "../../src/libs/types";
import type { Session } from "../../src/libs/types";
import * as log from "electron-log";
import { post } from "./v1-client";
import { deepReadDir } from "./tea-dir";
import path from "path";
import { installPackage, openTerminal } from "./cli";
import { getUpdater } from "./auto-updater";
import fetch from "node-fetch";
let teaProtocolPath = ""; // this should be empty string
export const setProtocolPath = (path: string) => {
@ -85,4 +89,45 @@ export default function initializeHandlers() {
teaProtocolPath = "";
return path;
});
ipcMain.handle("submit-logs", async () => {
try {
log.info("syncing logs");
const logDir = path.join(app.getPath("home"), "Library/Logs/tea");
// ['/Users/neil/Library/Logs/tea/main.log']
const logFiles = await deepReadDir({ dir: logDir });
let deviceId = "";
const files = logFiles.map((p) => {
const paths = p.split("/");
deviceId = paths[2]; // temp hack use developers username instead of gui_id
return paths.pop();
});
const signedUrls = await post<{ [key: string]: string }>(`/gui/${deviceId}/sync-log-files`, {
files
});
if (signedUrls) {
for (const key in signedUrls) {
const fileIndex = files.indexOf(key);
const filePath = logFiles[fileIndex];
if (filePath) {
const payload = createReadStream(filePath);
const response = await fetch(signedUrls[key], {
method: "PUT",
body: payload,
headers: {
"Content-Length": statSync(filePath).size.toString()
}
});
log.info("uploading log:", key, response.status);
}
}
}
return `log files(${logFiles.length}) has been uploaded to S3 logs/${deviceId}`;
} catch (error) {
log.error(error);
return error.message;
}
});
}

View file

@ -87,7 +87,7 @@ export const getPkgBottles = (packageDir: Dir): string[] => {
return foundBottles;
};
const deepReadDir = async ({
export const deepReadDir = async ({
dir,
continueDeeper,
filter

View file

@ -2,7 +2,7 @@
import { authStore } from '$libs/stores';
import SelectLang from '$components/select-lang/select-lang.svelte';
import { baseUrl } from '$libs/v1-client';
import { shellOpenExternal } from '@native';
import { shellOpenExternal, submitLogs } from '@native';
const { user, deviceIdStore } = authStore;
const openGithub = () => {
@ -13,6 +13,15 @@
console.error(error);
}
};
let submittedMessage = "";
const onSubmitLogs = async () => {
if (submittedMessage !== "syncing...") {
submittedMessage = "syncing..."
const msg = await submitLogs();
submittedMessage = msg;
}
}
</script>
<nav class="bg-opacity-20 w-full h-full p-4">
{#if $user}
@ -29,4 +38,12 @@
</button>
{/if}
<SelectLang/>
<button
class={`mt-2 border transition-all border-gray rounded-sm w-full mb-2 h-8 text-center hover:bg-gray focus:bg-secondary ${submittedMessage === "syncing..." && "animate-pulse"}`}
on:click={onSubmitLogs}>
SUBMIT LOGS
</button>
{#if submittedMessage}
<p class="text-gray text-xs mt-2">{submittedMessage}</p>
{/if}
</nav>

View file

@ -207,3 +207,8 @@ export const getProtocolPath = async (): Promise<string> => {
const path = await ipcRenderer.invoke("get-protocol-path");
return path;
};
export const submitLogs = async () => {
const response = await ipcRenderer.invoke("submit-logs");
return response;
};

View file

@ -336,3 +336,7 @@ export const relaunch = () => {
};
export const getProtocolPath = async (): Promise<string> => "";
export const submitLogs = async () => {
return "synced!";
};

View file

@ -84,7 +84,6 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
const i = pkgs.findIndex((pkg) => pkg.full_name === pkgName);
if (i >= 0) {
const pkg = pkgs[i];
console.log(bottles, pkg);
const availableVersionsRaw = bottles
.map(({ version }) => version)