auth initiate, database and more

This commit is contained in:
DecDuck
2024-10-08 13:17:06 +11:00
parent 78fc668923
commit 22b1aeec9f
43 changed files with 956 additions and 84 deletions

24
app.vue
View File

@ -1,14 +1,24 @@
<template>
<div class="flex flex-col bg-zinc-900 h-screen w-screen overflow-hidden">
<Header class="select-none" />
<div class="grow overflow-y-scroll">
<div class="h-[200vh]" />
</div>
</div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
{{ state }}
</template>
<script setup lang="ts">
import { invoke } from "@tauri-apps/api/core";
// @ts-expect-error
import { AppStatus } from "./types.d.ts";
const state = await invoke("fetch_state");
const router = useRouter();
const state: { status: AppStatus } = await invoke("fetch_state");
switch (state.status) {
case AppStatus.NotConfigured:
router.push("/setup");
break;
case AppStatus.SignedOut:
router.push("/auth");
break;
}
</script>

View File

@ -1,3 +1,51 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind utilities;
$motiva: (
("MotivaSansThin.ttf", "ttf", 100, normal),
("MotivaSansLight.woff.ttf", "woff", 300, normal),
("MotivaSansRegular.woff.ttf", "woff", 400, normal),
("MotivaSansMedium.woff.ttf", "woff", 500, normal),
("MotivaSansBold.woff.ttf", "woff", 600, normal),
("MotivaSansExtraBold.ttf", "woff", 700, normal),
("MotivaSansBlack.woff.ttf", "woff", 900, normal)
);
$helvetica: (
("Helvetica.woff", "woff", 400, normal),
("Helvetica-Oblique.woff", "woff", 400, italic),
("Helvetica-Bold.woff", "woff", 600, normal),
("Helvetica-BoldOblique.woff", "woff", 600, italic),
("helvetica-light-587ebe5a59211.woff2", "woff2", 300, normal)
);
@each $file, $format, $weight, $style in $motiva {
@font-face {
font-family: "Motiva Sans";
src: url("/fonts/motiva/#{$file}") format($format);
font-weight: $weight;
font-style: $style;
}
}
@each $file, $format, $weight, $style in $helvetica {
@font-face {
font-family: "Helvetica";
src: url("/fonts/helvetica/#{$file}") format($format);
font-weight: $weight;
font-style: $style;
}
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter/InterVariable.ttf");
font-style: normal;
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter/InterVariable-Italic.ttf");
font-style: italic;
}

BIN
assets/wallpaper.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

@ -28,32 +28,7 @@
</li>
<HeaderUserWidget />
</ol>
<div class="ml-3 inline-flex h-6 gap-x-2">
<HeaderButton @click="() => window.minimize()">
<MinusIcon />
</HeaderButton>
<HeaderButton @click="() => window.maximize()">
<svg
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect
x="6"
y="6"
width="12"
height="12"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</HeaderButton>
<HeaderButton @click="() => window.close()">
<XMarkIcon />
</HeaderButton>
</div>
<WindowControl class="ml-3" />
</div>
</div>
</template>
@ -61,9 +36,7 @@
<script setup lang="ts">
import {
BellIcon,
MinusIcon,
UserGroupIcon,
XMarkIcon,
} from "@heroicons/vue/16/solid";
import type { NavigationItem, QuickActionNav } from "./types";
import HeaderWidget from "./HeaderWidget.vue";

View File

@ -0,0 +1,31 @@
<template>
<button
type="submit"
class="inline-flex h-9 items-center justify-center rounded-md bg-blue-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
>
<div v-if="props.loading" role="status">
<svg
aria-hidden="true"
class="w-5 h-5 text-transparent animate-spin fill-white"
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"
/>
</svg>
<span class="sr-only">Loading...</span>
</div>
<span v-else> <slot /> </span>
</button>
</template>
<script setup lang="ts">
const props = defineProps<{ loading: boolean }>();
</script>

17
components/MiniHeader.vue Normal file
View File

@ -0,0 +1,17 @@
<template>
<div
@mousedown="() => window.startDragging()"
class="cursor-pointer flex flex-row items-center justify-between bg-zinc-950 px-3 py-2"
>
<div>
<Wordmark />
</div>
<WindowControl />
</div>
</template>
<script setup lang="ts">
import { getCurrentWindow } from "@tauri-apps/api/window";
const window = getCurrentWindow();
</script>

View File

@ -0,0 +1,34 @@
<template>
<div class="inline-flex items-center h-6 gap-x-2">
<HeaderButton @click="() => window.minimize()">
<MinusIcon />
</HeaderButton>
<HeaderButton @click="() => window.maximize()">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect
x="6"
y="6"
width="12"
height="12"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</HeaderButton>
<HeaderButton @click="() => window.close()">
<XMarkIcon />
</HeaderButton>
</div>
</template>
<script setup lang="ts">
import {
MinusIcon,
XMarkIcon,
} from "@heroicons/vue/16/solid";
import { getCurrentWindow } from "@tauri-apps/api/window";
const window = getCurrentWindow();
</script>

8
layouts/default.vue Normal file
View File

@ -0,0 +1,8 @@
<template>
<div class="flex flex-col bg-zinc-900 h-screen w-screen overflow-hidden">
<Header class="select-none" />
<div class="grow overflow-y-scroll">
<slot />
</div>
</div>
</template>

8
layouts/mini.vue Normal file
View File

@ -0,0 +1,8 @@
<template>
<div class="flex flex-col bg-zinc-950 h-screen w-screen overflow-hidden">
<MiniHeader class ="select-none" />
<div class="grow overflow-y-scroll">
<slot />
</div>
</div>
</template>

View File

@ -1,7 +1,6 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: "2024-04-03",
devtools: { enabled: true },
postcss: {
plugins: {

View File

@ -12,16 +12,17 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": ">=2.0.0",
"@tauri-apps/plugin-shell": ">=2.0.0",
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.1.5",
"@tauri-apps/api": ">=2.0.0",
"@tauri-apps/plugin-shell": ">=2.0.0",
"nuxt": "^3.13.0",
"scss": "^0.2.4",
"vue": "latest",
"vue-router": "latest"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.9",
"@tauri-apps/cli": ">=2.0.0",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.47",

71
pages/auth/index.vue Normal file
View File

@ -0,0 +1,71 @@
<template>
<div
class="grid min-h-full grid-cols-1 grid-rows-[1fr,auto,1fr] bg-zinc-950 lg:grid-cols-[max(50%,36rem),1fr]"
>
<header
class="mx-auto w-full max-w-7xl px-6 pt-6 sm:pt-10 lg:col-span-2 lg:col-start-1 lg:row-start-1 lg:px-8"
>
<Logo class="h-10 w-auto sm:h-12" />
</header>
<main
class="mx-auto w-full max-w-7xl px-6 py-24 sm:py-32 lg:col-span-2 lg:col-start-1 lg:row-start-2 lg:px-8"
>
<div class="max-w-lg">
<h1
class="mt-4 text-3xl font-bold font-display tracking-tight text-zinc-100 sm:text-5xl"
>
Sign in to Drop
</h1>
<p class="mt-6 text-base leading-7 text-zinc-400">
To get started, sign in to your Drop instance by clicking below.
</p>
<div class="mt-10">
<button
@click="() => auth()"
class="text-sm font-semibold leading-7 text-blue-600"
>
Sign in with your browser <span aria-hidden="true">&rarr;</span>
</button>
</div>
</div>
</main>
<footer class="self-end lg:col-span-2 lg:col-start-1 lg:row-start-3">
<div class="border-t border-blue-600 bg-zinc-900 py-10">
<nav
class="mx-auto flex w-full max-w-7xl items-center gap-x-4 px-6 text-sm leading-7 text-zinc-400 lg:px-8"
>
<a href="#">Documentation</a>
<svg
viewBox="0 0 2 2"
aria-hidden="true"
class="h-0.5 w-0.5 fill-zinc-700"
>
<circle cx="1" cy="1" r="1" />
</svg>
<a href="#">Troubleshooting</a>
</nav>
</div>
</footer>
<div
class="hidden lg:relative lg:col-start-2 lg:row-start-1 lg:row-end-4 lg:block"
>
<img
src="@/assets/wallpaper.jpg"
alt=""
class="absolute inset-0 h-full w-full object-cover"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { invoke } from "@tauri-apps/api/core";
async function auth() {
await invoke("auth_initiate");
}
definePageMeta({
layout: "mini",
});
</script>

1
pages/index.vue Normal file
View File

@ -0,0 +1 @@
<template></template>

33
pages/setup/index.vue Normal file
View File

@ -0,0 +1,33 @@
<template>
<div
class="mx-auto flex flex-col items-center gap-y-4 max-w-2xl py-32 sm:py-48 lg:py-56"
>
<div>
<Wordmark />
</div>
<div class="text-center">
<h1
class="text-balance text-4xl font-bold font-display tracking-tight text-zinc-100 sm:text-6xl"
>
Let's get you set up
</h1>
<p class="mt-6 text-lg leading-8 text-zinc-400">
Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui lorem
cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.
</p>
<div class="mt-10 flex items-center justify-center gap-x-6">
<NuxtLink
href="/setup/server"
class="rounded-md bg-blue-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
>Get started -></NuxtLink
>
</div>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: "mini",
});
</script>

113
pages/setup/server.vue Normal file
View File

@ -0,0 +1,113 @@
<template>
<div
class="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8"
>
<div class="sm:mx-auto sm:w-full sm:max-w-sm flex flex-col items-center">
<Wordmark />
<h2
class="mt-10 text-center text-2xl font-bold font-display leading-9 tracking-tight text-zinc-100"
>
Connect to your Drop instance
</h2>
</div>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<form class="space-y-6" @submit.prevent="connect_wrapper">
<div>
<label
for="company-website"
class="block text-sm font-medium leading-6 text-zinc-100"
>Drop instance address</label
>
<div class="mt-2">
<div
class="flex rounded-md shadow-sm ring-1 ring-inset ring-zinc-700 focus-within:ring-2 focus-within:ring-inset focus-within:ring-blue-600 sm:max-w-md"
>
<span
v-if="!url.startsWith('http')"
class="flex select-none items-center pl-3 text-zinc-500 -mr-2.5 sm:text-sm"
>https://</span
>
<input
type="text"
name="company-website"
id="company-website"
v-model="url"
class="block flex-1 border-0 bg-transparent py-1.5 text-zinc-100 placeholder:text-zinc-400 focus:ring-0 sm:text-sm sm:leading-6"
placeholder="www.example.com"
/>
</div>
</div>
</div>
<div>
<LoadingButton :loading="loading" class="w-full">
Continue ->
</LoadingButton>
</div>
<div v-if="error" class="mt-1 rounded-md bg-red-600/10 p-4">
<div class="flex">
<div class="flex-shrink-0">
<XCircleIcon class="h-5 w-5 text-red-600" aria-hidden="true" />
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-600">
{{ error }}
</h3>
</div>
</div>
</div>
</form>
<p class="mt-10 text-center text-sm text-gray-500">
Don't have one?
{{ " " }}
<a
href="https://github.com/Drop-OSS"
target="_blank"
class="font-semibold leading-6 text-blue-600 hover:text-blue-500"
>Host your own instance -></a
>
</p>
</div>
</div>
</template>
<script setup lang="ts">
import { XCircleIcon } from "@heroicons/vue/16/solid";
import { invoke } from "@tauri-apps/api/core";
definePageMeta({
layout: "mini",
});
const url = ref("");
const error = ref(undefined);
const loading = ref(false);
const router = useRouter();
async function connect() {
const newUrl = url.value.startsWith("http")
? url.value
: `https://${url.value}`;
const result = await invoke("use_remote", { url: newUrl });
router.push("/auth");
}
function connect_wrapper() {
loading.value = true;
error.value = undefined;
connect()
.then(() => {})
.catch((e) => {
console.log(e);
error.value = e;
})
.finally(() => {
loading.value = false;
});
}
</script>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

371
src-tauri/Cargo.lock generated
View File

@ -85,6 +85,12 @@ dependencies = [
"system-deps",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "autocfg"
version = "1.4.0"
@ -386,9 +392,9 @@ dependencies = [
"bitflags 2.6.0",
"block",
"cocoa-foundation",
"core-foundation",
"core-foundation 0.10.0",
"core-graphics",
"foreign-types",
"foreign-types 0.5.0",
"libc",
"objc",
]
@ -401,7 +407,7 @@ checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d"
dependencies = [
"bitflags 2.6.0",
"block",
"core-foundation",
"core-foundation 0.10.0",
"core-graphics-types",
"libc",
"objc",
@ -423,6 +429,16 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation"
version = "0.10.0"
@ -446,9 +462,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1"
dependencies = [
"bitflags 2.6.0",
"core-foundation",
"core-foundation 0.10.0",
"core-graphics-types",
"foreign-types",
"foreign-types 0.5.0",
"libc",
]
@ -459,7 +475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [
"bitflags 2.6.0",
"core-foundation",
"core-foundation 0.10.0",
"libc",
]
@ -710,13 +726,17 @@ version = "0.1.0"
dependencies = [
"ciborium",
"directories",
"os_info",
"rayon",
"reqwest",
"rustbreak",
"serde",
"serde_json",
"tauri",
"tauri-build",
"tauri-plugin-shell",
"url",
"webbrowser",
"zstd",
]
@ -858,6 +878,15 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared 0.1.1",
]
[[package]]
name = "foreign-types"
version = "0.5.0"
@ -865,7 +894,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
"foreign-types-macros",
"foreign-types-shared",
"foreign-types-shared 0.3.1",
]
[[package]]
@ -879,6 +908,12 @@ dependencies = [
"syn 2.0.79",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "foreign-types-shared"
version = "0.3.1"
@ -1270,6 +1305,25 @@ dependencies = [
"syn 2.0.79",
]
[[package]]
name = "h2"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
dependencies = [
"atomic-waker",
"bytes",
"fnv",
"futures-core",
"futures-sink",
"http",
"indexmap 2.6.0",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "half"
version = "2.4.1"
@ -1316,6 +1370,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "html5ever"
version = "0.26.0"
@ -1379,6 +1442,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
@ -1389,6 +1453,39 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-rustls"
version = "0.27.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333"
dependencies = [
"futures-util",
"http",
"hyper",
"hyper-util",
"rustls",
"rustls-pki-types",
"tokio",
"tokio-rustls",
"tower-service",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
dependencies = [
"bytes",
"http-body-util",
"hyper",
"hyper-util",
"native-tls",
"tokio",
"tokio-native-tls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.9"
@ -1820,6 +1917,23 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "native-tls"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "ndk"
version = "0.9.0"
@ -2054,12 +2168,67 @@ dependencies = [
"pathdiff",
]
[[package]]
name = "openssl"
version = "0.10.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"foreign-types 0.3.2",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.79",
]
[[package]]
name = "openssl-probe"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "os_info"
version = "3.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092"
dependencies = [
"log",
"serde",
"windows-sys 0.52.0",
]
[[package]]
name = "os_pipe"
version = "1.2.1"
@ -2576,25 +2745,33 @@ checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b"
dependencies = [
"base64 0.22.1",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-tls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-native-tls",
"tokio-util",
"tower-service",
"url",
@ -2605,6 +2782,21 @@ dependencies = [
"windows-registry",
]
[[package]]
name = "ring"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if",
"getrandom 0.2.15",
"libc",
"spin",
"untrusted",
"windows-sys 0.52.0",
]
[[package]]
name = "rustbreak"
version = "2.0.0"
@ -2646,6 +2838,45 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "rustls"
version = "0.23.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8"
dependencies = [
"once_cell",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55"
[[package]]
name = "rustls-webpki"
version = "0.102.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]]
name = "ryu"
version = "1.0.18"
@ -2661,6 +2892,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "schemars"
version = "0.8.21"
@ -2694,6 +2934,29 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.6.0",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "selectors"
version = "0.22.0"
@ -2944,7 +3207,7 @@ dependencies = [
"bytemuck",
"cfg_aliases",
"core-graphics",
"foreign-types",
"foreign-types 0.5.0",
"js-sys",
"log",
"objc2",
@ -2983,6 +3246,12 @@ dependencies = [
"system-deps",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
@ -3021,6 +3290,12 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "swift-rs"
version = "1.0.7"
@ -3063,6 +3338,27 @@ dependencies = [
"futures-core",
]
[[package]]
name = "system-configuration"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.6.0",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "system-deps"
version = "6.2.2"
@ -3084,7 +3380,7 @@ checksum = "a0dbbebe82d02044dfa481adca1550d6dd7bd16e086bc34fa0fbecceb5a63751"
dependencies = [
"bitflags 2.6.0",
"cocoa",
"core-foundation",
"core-foundation 0.10.0",
"core-graphics",
"crossbeam-channel",
"dispatch",
@ -3485,6 +3781,27 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
dependencies = [
"rustls",
"rustls-pki-types",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.12"
@ -3689,6 +4006,12 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.2"
@ -3729,6 +4052,12 @@ dependencies = [
"serde",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version-compare"
version = "0.2.0"
@ -3882,6 +4211,24 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webbrowser"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e5f07fb9bc8de2ddfe6b24a71a75430673fd679e568c48b52716cef1cfae923"
dependencies = [
"block2",
"core-foundation 0.10.0",
"home",
"jni",
"log",
"ndk-context",
"objc2",
"objc2-foundation",
"url",
"web-sys",
]
[[package]]
name = "webkit2gtk"
version = "2.0.1"
@ -4415,6 +4762,12 @@ dependencies = [
"syn 2.0.79",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zstd"
version = "0.13.2"

View File

@ -26,8 +26,15 @@ ciborium = "0.2.2"
zstd = "0.13.2"
rayon = "1.10.0"
directories = "5.0.1"
webbrowser = "1.0.2"
url = "2.5.2"
os_info = "3.8.2"
[dependencies.rustbreak]
version = "2"
features = ["bin_enc"] # You can also use "yaml_enc" or "ron_enc"
# Check the documentation to add your own!
features = ["bin_enc"] # You can also use "yaml_enc" or "bin_enc"
[dependencies.reqwest]
version = "0.12"
features = ["json"]

View File

@ -1,14 +1,63 @@
use std::{
borrow::{Borrow, BorrowMut},
sync::Mutex,
};
use serde::{Deserialize, Serialize};
use tauri::Error;
use url::Url;
use crate::{data::DatabaseInterface, AppAuthenticationStatus, User};
use crate::{data::DatabaseInterface, AppState, AppStatus, User, DB};
#[derive(Serialize)]
struct InitiateRequestBody {
name: String,
platform: String,
}
#[tauri::command]
pub async fn auth_initiate<'a>() -> Result<(), String> {
let base_url = {
let db_lock = DB.borrow_data().unwrap();
Url::parse(&db_lock.base_url.clone()).unwrap()
};
let current_os_info = os_info::get();
let endpoint = base_url.join("/api/v1/client/initiate").unwrap();
let body = InitiateRequestBody {
name: format!("Drop Desktop Client"),
platform: current_os_info.os_type().to_string(),
};
let client = reqwest::Client::new();
let response = client
.post(endpoint.to_string())
.json(&body)
.send()
.await
.unwrap();
let redir_url = response.text().await.unwrap();
let complete_redir_url = base_url.join(&redir_url).unwrap();
webbrowser::open(&complete_redir_url.to_string()).unwrap();
return Ok(());
}
pub fn setup() -> Result<(AppStatus, Option<User>), Error> {
let data = DB.borrow_data().unwrap();
pub fn setup(db: DatabaseInterface) -> Result<(AppAuthenticationStatus, Option<User>), Error> {
let data = db.get_data(true).unwrap();
// If we have certs, exit for now
if data.certs.is_some() {
// TODO: check if it's still valid, and fetch user information
return Ok((AppAuthenticationStatus::SignedInNeedsReauth, None));
return Ok((AppStatus::SignedInNeedsReauth, None));
}
return Ok((AppAuthenticationStatus::SignedOut, None));
drop(data);
auth_initiate();
return Ok((AppStatus::SignedOut, None));
}

View File

@ -1,32 +1,40 @@
use std::fs::create_dir_all;
use std::fs;
use directories::BaseDirs;
use rustbreak::{deser::Bincode, FileDatabase, PathDatabase};
use serde::{Deserialize, Serialize};
use rustbreak::{deser::Bincode, PathDatabase};
use serde::Deserialize;
#[derive(Serialize, Deserialize, Clone)]
use crate::DB;
#[derive(serde::Serialize, Clone, Deserialize)]
pub struct DatabaseCerts {
pub private: String,
pub public: String,
pub cert: String,
}
#[derive(Serialize, Clone, Deserialize)]
#[derive(serde::Serialize, Clone, Deserialize)]
pub struct Database {
pub certs: Option<DatabaseCerts>,
pub base_url: String,
}
pub type DatabaseInterface =
rustbreak::Database<Database, rustbreak::backend::PathBackend, Bincode>;
pub type DatabaseInterface = rustbreak::Database<Database, rustbreak::backend::PathBackend, Bincode>;
pub fn setup() -> DatabaseInterface {
let db_path = BaseDirs::new().unwrap().data_dir().join("drop");
let default = Database {
certs: None
certs: None,
base_url: "".to_string(),
};
let db = match fs::exists(db_path.clone()).unwrap() {
true => PathDatabase::load_from_path(db_path).expect("Database loading failed"),
false => PathDatabase::create_at_path(db_path, default).unwrap(),
};
let db = PathDatabase::<Database, Bincode>::create_at_path(db_path, default).unwrap();
db.save().unwrap();
return db;
}
pub fn is_set_up() -> bool {
return !DB.borrow_data().unwrap().base_url.is_empty();
}

View File

@ -1,13 +1,21 @@
mod auth;
mod data;
mod remote;
mod unpacker;
use std::{
borrow::Borrow,
sync::{LazyLock, Mutex},
};
use auth::auth_initiate;
use data::DatabaseInterface;
use remote::use_remote;
use serde::Serialize;
use tauri::Runtime;
#[derive(Clone, Copy, Serialize)]
pub enum AppAuthenticationStatus {
pub enum AppStatus {
NotConfigured,
SignedOut,
SignedIn,
SignedInNeedsReauth,
@ -17,28 +25,47 @@ pub struct User {}
#[derive(Clone, Copy, Serialize)]
pub struct AppState {
auth: AppAuthenticationStatus,
status: AppStatus,
user: Option<User>,
}
#[tauri::command]
fn fetch_state(state: tauri::State<AppState>) -> Result<AppState, String> {
Ok(*state.inner())
fn fetch_state<'a>(state: tauri::State<'_, Mutex<AppState>>) -> Result<AppState, String> {
let guard = state.lock().unwrap();
let cloned_state = guard.clone();
drop(guard);
Ok(cloned_state)
}
fn setup<'a>() -> AppState {
let is_set_up = data::is_set_up();
if !is_set_up {
return AppState {
status: AppStatus::NotConfigured,
user: None,
};
}
let auth_result = auth::setup().unwrap();
return AppState {
status: auth_result.0,
user: auth_result.1,
};
}
pub static DB: LazyLock<DatabaseInterface> = LazyLock::new(|| data::setup());
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let db: DatabaseInterface = data::setup();
let auth_result = auth::setup(db).unwrap();
let state = AppState {
auth: auth_result.0,
user: auth_result.1,
};
let state = setup();
tauri::Builder::default()
.manage(state)
.invoke_handler(tauri::generate_handler![fetch_state])
.manage(Mutex::new(state))
.invoke_handler(tauri::generate_handler![
fetch_state,
auth_initiate,
use_remote
])
.plugin(tauri_plugin_shell::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");

View File

@ -4,3 +4,4 @@
fn main() {
drop_app_lib::run()
}

59
src-tauri/src/remote.rs Normal file
View File

@ -0,0 +1,59 @@
use std::{
borrow::{Borrow, BorrowMut},
sync::Mutex,
};
use serde::Deserialize;
use url::Url;
use crate::{AppState, AppStatus, DB};
macro_rules! unwrap_or_return {
( $e:expr ) => {
match $e {
Ok(x) => x,
Err(e) => {
return Err(format!(
"Invalid URL or Drop is inaccessible ({})",
e.to_string()
))
}
}
};
}
#[derive(Deserialize)]
struct DropHealthcheck {
appName: String,
}
#[tauri::command]
pub async fn use_remote<'a>(
url: String,
state: tauri::State<'_, Mutex<AppState>>,
) -> Result<(), String> {
println!("connecting to url {}", url);
let base_url = unwrap_or_return!(Url::parse(&url));
// Test Drop url
let test_endpoint = base_url.join("/api/v1").unwrap();
let response = unwrap_or_return!(reqwest::get(test_endpoint.to_string()).await);
let result = response.json::<DropHealthcheck>().await.unwrap();
if result.appName != "Drop" {
return Err("Not a valid Drop endpoint".to_string());
}
let mut app_state = state.lock().unwrap();
app_state.status = AppStatus::SignedOut;
drop(app_state);
let mut db_state = DB.borrow_data_mut().unwrap();
db_state.base_url = base_url.to_string();
drop(db_state);
DB.save().unwrap();
return Ok(());
}

View File

@ -4,8 +4,8 @@
"version": "0.1.0",
"identifier": "dev.drop.drop",
"build": {
"beforeDevCommand": "yarn dev",
"devUrl": "http://localhost:3000",
"beforeDevCommand": "yarn dev --port 1432",
"devUrl": "http://localhost:1432",
"beforeBuildCommand": "yarn generate",
"frontendDist": "../.output/public"
},
@ -26,7 +26,6 @@
},
"bundle": {
"active": true,
"targets": ["msi", "deb"],
"icon": [
"icons/32x32.png",
"icons/128x128.png",

View File

@ -10,7 +10,11 @@ export default {
],
theme: {
extend: {
fontFamily: {
sans: ["Inter"],
display: ["Motiva Sans"],
},
},
},
plugins: [],
plugins: [require("@tailwindcss/forms")],
};

6
types.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
export enum AppStatus {
NotConfigured = "NotConfigured",
SignedOut = "SignedOut",
SignedIn = "SignedIn",
SignedInNeedsReauth = "SignedInNeedsReauth",
}

View File

@ -1238,6 +1238,13 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958"
integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==
"@tailwindcss/forms@^0.5.9":
version "0.5.9"
resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.9.tgz#b495c12575d6eae5865b2cbd9876b26d89f16f61"
integrity sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==
dependencies:
mini-svg-data-uri "^1.2.3"
"@tanstack/virtual-core@3.10.8":
version "3.10.8"
resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.10.8.tgz#975446a667755222f62884c19e5c3c66d959b8b4"
@ -3472,6 +3479,11 @@ mimic-fn@^4.0.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
mini-svg-data-uri@^1.2.3:
version "1.4.4"
resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939"
integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==
minimatch@^3.0.4, minimatch@^3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"