add login mechanic

This commit is contained in:
HorizonCode 2024-01-11 01:00:43 +01:00
parent 6790fe5ef6
commit 05b9ddd5a1
7 changed files with 138 additions and 67 deletions

20
main.js
View File

@ -16,9 +16,23 @@ function isDev() {
}
function registerIPCPipes() {
ipcMain.handle("ezpplauncher:login", (e, args) => {
console.log(args);
return "yes";
ipcMain.handle("ezpplauncher:login", async (e, args) => {
const fetchResult = await fetch("https://ez-pp.farm/login/check", {
method: "POST",
body: JSON.stringify({ username: args.username, password: args.password }),
headers: {
"Content-Type": "application/json",
},
});
if (fetchResult.ok) {
const result = await fetchResult.json();
if (result.code == 200) return result;
}
return {
code: 403,
message: "Invalid username or password.",
}
});
}

57
package-lock.json generated
View File

@ -11,7 +11,8 @@
"dependencies": {
"axios": "^1.6.5",
"custom-electron-titlebar": "^4.2.7",
"electron-serve": "^1.1.0"
"electron-serve": "^1.1.0",
"svelte-french-toast": "^1.2.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
@ -62,7 +63,6 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
"integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
@ -860,7 +860,6 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@ -874,7 +873,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
@ -883,7 +881,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
@ -901,14 +898,12 @@
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.20",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
"integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@ -1487,8 +1482,7 @@
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
},
"node_modules/@types/fs-extra": {
"version": "9.0.13",
@ -1598,7 +1592,6 @@
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
@ -1833,7 +1826,6 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"dev": true,
"dependencies": {
"dequal": "^2.0.3"
}
@ -1938,7 +1930,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
"integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
"dev": true,
"dependencies": {
"dequal": "^2.0.3"
}
@ -2400,7 +2391,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz",
"integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15",
"@types/estree": "^1.0.1",
@ -2413,7 +2403,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0"
}
@ -2647,7 +2636,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
"dev": true,
"dependencies": {
"mdn-data": "2.0.30",
"source-map-js": "^1.0.1"
@ -2930,7 +2918,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -4453,8 +4440,7 @@
"node_modules/locate-character": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"dev": true
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="
},
"node_modules/lodash": {
"version": "4.17.21",
@ -4504,7 +4490,6 @@
"version": "0.30.5",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
"integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
@ -4527,8 +4512,7 @@
"node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"dev": true
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
},
"node_modules/merge2": {
"version": "1.4.1",
@ -4938,7 +4922,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^3.0.0",
@ -4949,7 +4932,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0"
}
@ -4958,7 +4940,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz",
"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
"dev": true,
"dependencies": {
"@types/estree": "*"
}
@ -6483,7 +6464,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -6739,7 +6719,6 @@
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.8.tgz",
"integrity": "sha512-hU6dh1MPl8gh6klQZwK/n73GiAHiR95IkFsesLPbMeEZi36ydaXL/ZAb4g9sayT0MXzpxyZjR28yderJHxcmYA==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.1",
"@jridgewell/sourcemap-codec": "^1.4.15",
@ -6781,6 +6760,17 @@
"svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0"
}
},
"node_modules/svelte-french-toast": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/svelte-french-toast/-/svelte-french-toast-1.2.0.tgz",
"integrity": "sha512-5PW+6RFX3xQPbR44CngYAP1Sd9oCq9P2FOox4FZffzJuZI2mHOB7q5gJBVnOiLF5y3moVGZ7u2bYt7+yPAgcEQ==",
"dependencies": {
"svelte-writable-derived": "^3.1.0"
},
"peerDependencies": {
"svelte": "^3.57.0 || ^4.0.0"
}
},
"node_modules/svelte-hmr": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz",
@ -6856,11 +6846,21 @@
}
}
},
"node_modules/svelte-writable-derived": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/svelte-writable-derived/-/svelte-writable-derived-3.1.0.tgz",
"integrity": "sha512-cTvaVFNIJ036vSDIyPxJYivKC7ZLtcFOPm1Iq6qWBDo1fOHzfk6ZSbwaKrxhjgy52Rbl5IHzRcWgos6Zqn9/rg==",
"funding": {
"url": "https://ko-fi.com/pixievoltno1"
},
"peerDependencies": {
"svelte": "^3.2.1 || ^4.0.0-next.1"
}
},
"node_modules/svelte/node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0"
}
@ -6869,7 +6869,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz",
"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
"dev": true,
"dependencies": {
"@types/estree": "*"
}

View File

@ -35,7 +35,8 @@
"dependencies": {
"axios": "^1.6.5",
"custom-electron-titlebar": "^4.2.7",
"electron-serve": "^1.1.0"
"electron-serve": "^1.1.0",
"svelte-french-toast": "^1.2.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",

View File

@ -1,4 +1,5 @@
const { Titlebar, TitlebarColor } = require("custom-electron-titlebar");
const { ipcRenderer } = require("electron");
window.addEventListener("DOMContentLoaded", () => {
const titlebar = new Titlebar({
@ -8,6 +9,12 @@ window.addEventListener("DOMContentLoaded", () => {
enableMnemonics: false,
maximizable: false,
});
//titlebar.updateTitle(`${appInfo.appName} ${appInfo.appVersion}`);
});
window.addEventListener("login-attempt", async (e) => {
const loginResult = await ipcRenderer.invoke("ezpplauncher:login", {
username: e.detail.username,
password: e.detail.password,
});
window.dispatchEvent(new CustomEvent("login-result", { detail: loginResult }));
})

View File

@ -17,14 +17,24 @@
UserSolid,
} from "flowbite-svelte-icons";
import ezppLogo from "../public/favicon.png";
import { currentPage } from "./storage/localStore";
import { currentPage, currentUser } from "./storage/localStore";
import { Page } from "./consts/pages";
import Login from "./pages/Login.svelte";
import Launch from "./pages/Launch.svelte";
import { Toaster } from "svelte-french-toast";
import type { User } from "./types/user";
let user: User | undefined = undefined;
let loggedIn = false;
currentUser.subscribe((newUser) => {
loggedIn = newUser != undefined;
user = newUser;
});
</script>
<Toaster></Toaster>
<div class="p-2 flex flex-row justify-between items-center">
<div class="flex flex-row items-center">
<img src={ezppLogo} alt="EZPPFarm Logo" class="w-12 h-12 mr-2" />
@ -36,38 +46,43 @@
<div class="flex flex-row gap-2 w-fill cursor-pointer md:order-2">
<Avatar
class="rounded-lg border dark:border-gray-700 hover:ring-4 hover:ring-gray-200 dark:hover:ring-gray-800"
src={loggedIn ? "https://a.ez-pp.farm/1001" : "https://a.ez-pp.farm/0"}
src={loggedIn
? "https://a.ez-pp.farm/" + user?.id
: "https://a.ez-pp.farm/0"}
id="avatar-menu"
/>
</div>
<Dropdown placement="bottom" triggeredBy="#avatar-menu">
<DropdownHeader>
<span class="block text-sm">{loggedIn ? "Quetzalcoatl" : "Guest"}</span>
<span class="block text-sm">{loggedIn ? user?.name : "Guest"}</span>
<span
class="block truncate text-sm font-medium text-gray-500 dark:text-gray-200"
>
{loggedIn ? "me@horizonco.de" : "Please log in!"}
{loggedIn ? user?.email : "Please log in!"}
</span>
</DropdownHeader>
{#if loggedIn}
<DropdownItem
<!-- <DropdownItem
class="flex flex-row gap-2 border-0 dark:!bg-gray-700 dark:active:!bg-gray-900 dark:hover:!bg-gray-800 transition-colors"
>
<UserSolid class="select-none outline-none border-none" />
Profile
</DropdownItem>
</DropdownItem> -->
{/if}
<DropdownItem
<!-- <DropdownItem
class="flex flex-row gap-2 border-0 dark:!bg-gray-700 dark:active:!bg-gray-900 dark:hover:!bg-gray-800 transition-colors"
>
<UserSettingsSolid class="select-none outline-none border-none" />
Settings
</DropdownItem>
<DropdownDivider />
</DropdownItem>
<DropdownDivider />-->
{#if loggedIn}
<DropdownItem
class="flex flex-row gap-2 border-0 dark:!bg-gray-700 dark:active:!bg-gray-900 dark:hover:!bg-gray-800 transition-colors"
on:click={() => (loggedIn = false)}
on:click={() => {
currentUser.set(undefined);
currentPage.set(Page.Login);
}}
>
<ArrowRightFromBracketSolid
class="select-none outline-none border-none"
@ -84,12 +99,12 @@
/>
Login
</DropdownItem>
<DropdownItem
<!-- <DropdownItem
class="flex flex-row gap-2 border-0 dark:!bg-gray-700 dark:active:!bg-gray-900 dark:hover:!bg-gray-800 transition-colors"
>
<UserPlusSolid class="select-none outline-none border-none" />
Register
</DropdownItem>
</DropdownItem> -->
{/if}
</Dropdown>
{/if}

View File

@ -2,7 +2,10 @@
import { Input, Button, Spinner } from "flowbite-svelte";
import { performLogin } from "../util/loginUtil";
import type { User } from "../types/user";
import { currentUser } from "../storage/localStore";
import type { Error } from "../types/error";
import { currentPage, currentUser } from "../storage/localStore";
import toast from "svelte-french-toast";
import { Page } from "../consts/pages";
let loading = false;
let username = "";
@ -10,11 +13,38 @@
const processLogin = async () => {
loading = true;
const loginResult = await performLogin(username, password);
if (loginResult instanceof Error) {
loading = false;
return;
}
window.addEventListener(
"login-result",
(e) => {
const customEvent = e as CustomEvent;
const resultData = customEvent.detail;
const wasSuccessful = "user" in resultData;
if (!wasSuccessful) {
toast.error(resultData.message, {
position: "bottom-center",
className:
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
duration: 1500,
});
loading = false;
return;
}
console.log(resultData);
currentUser.set(resultData.user as User);
currentPage.set(Page.Launch);
toast.success(`Welcome back ${resultData.user.name}!`, {
position: "bottom-center",
className:
"dark:!bg-gray-800 border-1 dark:!border-gray-700 dark:!text-gray-100",
duration: 5000,
});
},
{ once: true }
);
window.dispatchEvent(
new CustomEvent("login-attempt", { detail: { username, password } })
);
};
</script>
@ -52,7 +82,9 @@
<Button
class="!bg-transparent border-none dark:text-gray-700 hover:!bg-gray-700/15 ring-primary active:ring-2 focus:ring-2"
color="none"
disabled={loading}>Continue without login</Button
disabled={loading}
on:click={() => currentPage.set(Page.Launch)}
>Continue without login</Button
>
</div>
</div>

View File

@ -1,7 +1,6 @@
import axios from "axios";
import type { Error } from "../types/error";
import type { User } from "../types/user";
import { ipcRenderer } from "electron";
const loginCheckEndpoint = "https://ez-pp.farm/login/check";
let retries = 0;
@ -9,22 +8,26 @@ let retries = 0;
export const performLogin = async (
username: string,
password: string,
) => {
const result = await ipcRenderer.invoke("ezpplauncher:login", {
username,
password,
): Promise<Error | User> => {
const fetchResult = await fetch("https://ez-pp.farm/login/check", {
method: "POST",
mode: "cors",
body: JSON.stringify({ username, password }),
headers: {
"Content-Type": "application/json",
},
});
console.log(result);
return ({ code: 403, message: "Login failed." } as Error);
/* const result = await axios.post(loginCheckEndpoint, { username, password });
const code = result.data.code ?? 404;
if (code === 200 || code === 403) {
if (fetchResult.ok) {
const result = await fetchResult.json();
retries = 0;
return result.data.user as User;
return result.user;
} else {
if (retries++ >= 5) {
return ({ code: 403, message: "Login failed." } as Error);
console.log("Login failed after 5 retries.");
retries = 0;
return { code: 403, message: "Login failed." } as Error;
}
return await performLogin(username, password);
} */
}
};